summaryrefslogtreecommitdiff
path: root/sgx/services4/srvkm
diff options
context:
space:
mode:
Diffstat (limited to 'sgx/services4/srvkm')
-rw-r--r--sgx/services4/srvkm/bridged/bridged_pvr_bridge.c1061
-rw-r--r--sgx/services4/srvkm/bridged/bridged_pvr_bridge.h96
-rw-r--r--sgx/services4/srvkm/bridged/bridged_support.c81
-rw-r--r--sgx/services4/srvkm/bridged/bridged_support.h78
-rw-r--r--sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c290
-rw-r--r--sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h72
-rw-r--r--sgx/services4/srvkm/common/buffer_manager.c1870
-rw-r--r--sgx/services4/srvkm/common/deviceclass.c1306
-rw-r--r--sgx/services4/srvkm/common/deviceid.h68
-rw-r--r--sgx/services4/srvkm/common/devicemem.c1639
-rw-r--r--sgx/services4/srvkm/common/handle.c1232
-rw-r--r--sgx/services4/srvkm/common/hash.c336
-rw-r--r--sgx/services4/srvkm/common/lists.c112
-rw-r--r--sgx/services4/srvkm/common/mem.c77
-rw-r--r--sgx/services4/srvkm/common/mem_debug.c131
-rw-r--r--sgx/services4/srvkm/common/metrics.c126
-rw-r--r--sgx/services4/srvkm/common/osfunc_common.c68
-rw-r--r--sgx/services4/srvkm/common/pdump_common.c1150
-rw-r--r--sgx/services4/srvkm/common/perproc.c180
-rw-r--r--sgx/services4/srvkm/common/power.c440
-rw-r--r--sgx/services4/srvkm/common/pvrsrv.c777
-rw-r--r--sgx/services4/srvkm/common/queue.c705
-rw-r--r--sgx/services4/srvkm/common/ra.c641
-rw-r--r--sgx/services4/srvkm/common/refcount.c584
-rw-r--r--sgx/services4/srvkm/common/resman.c493
-rw-r--r--sgx/services4/srvkm/devices/sgx/mmu.c2484
-rw-r--r--sgx/services4/srvkm/devices/sgx/mmu.h422
-rw-r--r--sgx/services4/srvkm/devices/sgx/pb.c110
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgx_bridge_km.h172
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxconfig.h263
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxinfokm.h277
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxinit.c1566
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxkick.c228
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxpower.c285
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxreset.c359
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxtransfer.c196
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxutils.c791
-rw-r--r--sgx/services4/srvkm/devices/sgx/sgxutils.h107
-rw-r--r--[-rwxr-xr-x]sgx/services4/srvkm/env/linux/Kbuild.mk84
-rw-r--r--[-rwxr-xr-x]sgx/services4/srvkm/env/linux/Linux.mk54
-rw-r--r--sgx/services4/srvkm/env/linux/env_data.h80
-rw-r--r--sgx/services4/srvkm/env/linux/env_perproc.h76
-rw-r--r--sgx/services4/srvkm/env/linux/event.c180
-rw-r--r--sgx/services4/srvkm/env/linux/event.h67
-rw-r--r--sgx/services4/srvkm/env/linux/linkage.h77
-rw-r--r--sgx/services4/srvkm/env/linux/lock.h77
-rw-r--r--sgx/services4/srvkm/env/linux/mm.c1706
-rw-r--r--sgx/services4/srvkm/env/linux/mm.h485
-rw-r--r--sgx/services4/srvkm/env/linux/mmap.c1082
-rw-r--r--sgx/services4/srvkm/env/linux/mmap.h197
-rw-r--r--sgx/services4/srvkm/env/linux/module.c577
-rw-r--r--sgx/services4/srvkm/env/linux/mutex.c74
-rw-r--r--sgx/services4/srvkm/env/linux/mutex.h77
-rw-r--r--sgx/services4/srvkm/env/linux/mutils.c99
-rw-r--r--sgx/services4/srvkm/env/linux/mutils.h69
-rw-r--r--sgx/services4/srvkm/env/linux/osfunc.c1988
-rw-r--r--sgx/services4/srvkm/env/linux/osperproc.c96
-rw-r--r--sgx/services4/srvkm/env/linux/pdump.c279
-rw-r--r--sgx/services4/srvkm/env/linux/private_data.h93
-rw-r--r--sgx/services4/srvkm/env/linux/proc.c644
-rw-r--r--sgx/services4/srvkm/env/linux/proc.h76
-rw-r--r--sgx/services4/srvkm/env/linux/pvr_bridge_k.c155
-rw-r--r--sgx/services4/srvkm/env/linux/pvr_debug.c193
-rw-r--r--sgx/services4/srvkm/env/linux/pvr_drm.c116
-rw-r--r--sgx/services4/srvkm/env/linux/pvr_drm.h70
-rw-r--r--sgx/services4/srvkm/env/linux/pvr_uaccess.h72
-rw-r--r--sgx/services4/srvkm/hwdefs/ocpdefs.h90
-rw-r--r--sgx/services4/srvkm/hwdefs/sgx530defs.h107
-rw-r--r--sgx/services4/srvkm/hwdefs/sgx540defs.h111
-rw-r--r--sgx/services4/srvkm/hwdefs/sgx544defs.h173
-rw-r--r--sgx/services4/srvkm/hwdefs/sgxdefs.h81
-rw-r--r--sgx/services4/srvkm/hwdefs/sgxerrata.h652
-rw-r--r--sgx/services4/srvkm/hwdefs/sgxfeaturedefs.h106
-rw-r--r--sgx/services4/srvkm/hwdefs/sgxmmu.h80
-rw-r--r--sgx/services4/srvkm/hwdefs/sgxmpdefs.h90
-rw-r--r--sgx/services4/srvkm/include/buffer_manager.h504
-rw-r--r--sgx/services4/srvkm/include/device.h267
-rw-r--r--sgx/services4/srvkm/include/handle.h232
-rw-r--r--sgx/services4/srvkm/include/hash.h250
-rw-r--r--sgx/services4/srvkm/include/lists.h156
-rw-r--r--sgx/services4/srvkm/include/metrics.h85
-rw-r--r--sgx/services4/srvkm/include/osfunc.h292
-rw-r--r--sgx/services4/srvkm/include/osperproc.h75
-rw-r--r--sgx/services4/srvkm/include/pdump_int.h96
-rw-r--r--sgx/services4/srvkm/include/pdump_km.h92
-rw-r--r--sgx/services4/srvkm/include/pdump_osfunc.h236
-rw-r--r--sgx/services4/srvkm/include/perfkm.h59
-rw-r--r--sgx/services4/srvkm/include/perproc.h97
-rw-r--r--sgx/services4/srvkm/include/power.h81
-rw-r--r--sgx/services4/srvkm/include/queue.h104
-rw-r--r--sgx/services4/srvkm/include/ra.h204
-rw-r--r--sgx/services4/srvkm/include/refcount.h204
-rw-r--r--sgx/services4/srvkm/include/resman.h163
-rw-r--r--sgx/services4/srvkm/include/services_headers.h72
-rw-r--r--sgx/services4/srvkm/include/srvkm.h110
-rw-r--r--sgx/services4/srvkm/include/ttrace.h75
-rw-r--r--sgx/services4/srvkm/include/ttrace_common.h120
-rw-r--r--sgx/services4/srvkm/include/ttrace_tokens.h85
98 files changed, 26106 insertions, 8759 deletions
diff --git a/sgx/services4/srvkm/bridged/bridged_pvr_bridge.c b/sgx/services4/srvkm/bridged/bridged_pvr_bridge.c
index f3b4cb0..f933477 100644
--- a/sgx/services4/srvkm/bridged/bridged_pvr_bridge.c
+++ b/sgx/services4/srvkm/bridged/bridged_pvr_bridge.c
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Common Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
@@ -46,6 +64,7 @@
#include "perproc.h"
#include "device.h"
#include "buffer_manager.h"
+#include "refcount.h"
#include "pdump_km.h"
#include "syscommon.h"
@@ -70,6 +89,18 @@
#include "srvkm.h"
+/* FIXME: we should include an OS specific header here to allow configuration of
+ * which functions should be excluded (like the shared srvclient bridge code)
+ * so that ports may choose to override certain things. */
+
+/* For the purpose of maintainability, it is intended that this file should not
+ * contain large amounts of OS specific #ifdefs. Headers are fine, and perhaps
+ * a few one liners, but for anything more, please find a way to add e.g.
+ * an osfunc.c abstraction or override the entire function in question within
+ * env,*,pvr_bridge_k.c
+ */
+
+
PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY g_BridgeDispatchTable[BRIDGE_DISPATCH_TABLE_ENTRY_COUNT];
#if defined(DEBUG_BRIDGE_KM)
@@ -147,7 +178,10 @@ PVRSRVAcquireDeviceDataBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /*
+ * Handle is not allocated in batch mode, as there is no resource
+ * allocation to undo if the handle allocation fails.
+ */
psAcquireDevInfoOUT->eError =
PVRSRVAllocHandle(psPerProc->psHandleBase,
&psAcquireDevInfoOUT->hDevCookie,
@@ -175,7 +209,10 @@ PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CREATE_DEVMEMCONTEXT);
-
+ /*
+ * We potentially need one handle for the device memory context,
+ * and one handle for each client heap.
+ */
NEW_HANDLE_BATCH_OR_ERROR(psCreateDevMemContextOUT->eError, psPerProc, PVRSRV_MAX_CLIENT_HEAPS + 1)
psCreateDevMemContextOUT->eError =
@@ -206,7 +243,11 @@ PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /*
+ * Only allocate a handle if the device memory context was created.
+ * If an existing context was returned, lookup the existing
+ * handle.
+ */
if(bCreated)
{
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
@@ -240,7 +281,13 @@ PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
if(abSharedDeviceMemHeap[i])
#endif
{
-
+ /*
+ * Heaps shared by everybody. These heaps are not
+ * created as part of the device memory context
+ * creation, and exist for the lifetime of the
+ * driver, hence, we use shared handles for these
+ * heaps.
+ */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&hDevMemHeapExt,
@@ -257,7 +304,12 @@ PVRSRVCreateDeviceMemContextBW(IMG_UINT32 ui32BridgeID,
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
else
{
-
+ /*
+ * Heaps belonging to this context. The handles for
+ * these are made subhandles of the memory context
+ * handle, so that they are automatically deallocated
+ * when the memory context handle is deallocated.
+ */
if(bCreated)
{
#if defined (SUPPORT_SID_INTERFACE)
@@ -425,7 +477,13 @@ PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
if(abSharedDeviceMemHeap[i])
#endif
{
-
+ /*
+ * Heaps shared by everybody. These heaps are not
+ * created as part of the device memory context
+ * creation, and exist for the lifetime of the
+ * driver, hence, we use shared handles for these
+ * heaps.
+ */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&hDevMemHeapExt,
@@ -442,7 +500,12 @@ PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
else
{
-
+ /*
+ * Heaps belonging to this context. The handles for
+ * these are made subhandles of the memory context
+ * handle, so that they are automatically deallocated
+ * when the memory context handle is deallocated.
+ */
psGetDevMemHeapInfoOUT->eError =
PVRSRVFindHandle(psPerProc->psHandleBase,
&hDevMemHeapExt,
@@ -475,6 +538,7 @@ PVRSRVGetDeviceMemHeapInfoBW(IMG_UINT32 ui32BridgeID,
#if defined(OS_PVRSRV_ALLOC_DEVICE_MEM_BW)
+/* customised version */
IMG_INT
PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *psAllocDeviceMemIN,
@@ -490,12 +554,32 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
IMG_HANDLE hDevCookieInt;
IMG_HANDLE hDevMemHeapInt;
- PXProcShareDataNode pShareDataNode = NULL;
+ IMG_UINT32 ui32ShareIndex;
+ IMG_BOOL bUseShareMemWorkaround;
+ IMG_BOOL *pabMapChunk = IMG_NULL;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ALLOC_DEVICEMEM);
NEW_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc, 2)
+ /* Do same sanity checking */
+ if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_SPARSE)
+ {
+ if (psAllocDeviceMemIN->ui32NumPhysChunks > psAllocDeviceMemIN->ui32NumVirtChunks)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: more physical chunks then virtual space"));
+ psAllocDeviceMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+
+ if (psAllocDeviceMemIN->pabMapChunk == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Called in sparse mapping mode but without MapChunk array"));
+ psAllocDeviceMemOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ return 0;
+ }
+ }
+
psAllocDeviceMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
psAllocDeviceMemIN->hDevCookie,
@@ -516,18 +600,74 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
- /* Start mutually exclusive region */
+ /* Memory sharing workaround, version 2 */
- if((psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_XPROC) != 0)
+ bUseShareMemWorkaround = ((psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_XPROC) != 0) ? IMG_TRUE : IMG_FALSE;
+ ui32ShareIndex = 7654321; /* stops MSVC compiler warning */
+
+ if (bUseShareMemWorkaround)
+ {
+ /* allocate a shared-surface ID, prior to the call to AllocDeviceMem */
+ /* We could plumb in an extra argument, but for now, we'll keep the
+ shared-surface ID as a piece of global state, and rely upon the
+ bridge mutex to make it safe for us */
+
+ psAllocDeviceMemOUT->eError =
+ BM_XProcWorkaroundFindNewBufferAndSetShareIndex(&ui32ShareIndex);
+ if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+ }
+
+ /* Check access to private data, if provided */
+ if(psAllocDeviceMemIN->pvPrivData)
+ {
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psAllocDeviceMemIN->pvPrivData,
+ psAllocDeviceMemIN->ui32PrivDataLength))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pvPrivData"));
+ return -EFAULT;
+ }
+ }
+
+ if (psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_SPARSE)
{
- pShareDataNode = BM_XProcAllocNewBuffer();
- if(pShareDataNode == NULL)
+ /* Check access to the sparse mapping table, if provided */
+ if(!OSAccessOK(PVR_VERIFY_READ,
+ psAllocDeviceMemIN->pabMapChunk,
+ psAllocDeviceMemIN->ui32NumVirtChunks))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVAllocDeviceMemBW: Access check failed for pabMapChunk"));
+ return -EFAULT;
+ }
+
+ psAllocDeviceMemOUT->eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks,
+ (IMG_VOID **) &pabMapChunk,
+ 0,
+ "MapChunk kernel copy");
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psAllocDeviceMemOUT->eError = OSCopyFromUser(psPerProc,
+ pabMapChunk,
+ psAllocDeviceMemIN->pabMapChunk,
+ sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks);
+ if (psAllocDeviceMemOUT->eError != PVRSRV_OK)
{
- psAllocDeviceMemOUT->eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_BOOL) * psAllocDeviceMemIN->ui32NumVirtChunks,
+ pabMapChunk,
+ 0);
return 0;
}
}
+
psAllocDeviceMemOUT->eError =
PVRSRVAllocDeviceMemKM(hDevCookieInt,
psPerProc,
@@ -535,26 +675,31 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
psAllocDeviceMemIN->ui32Attribs,
psAllocDeviceMemIN->ui32Size,
psAllocDeviceMemIN->ui32Alignment,
+ psAllocDeviceMemIN->pvPrivData,
+ psAllocDeviceMemIN->ui32PrivDataLength,
+ psAllocDeviceMemIN->ui32ChunkSize,
+ psAllocDeviceMemIN->ui32NumVirtChunks,
+ psAllocDeviceMemIN->ui32NumPhysChunks,
+ pabMapChunk,
&psMemInfo,
- "" );
+ "" /*FIXME: add something meaningful*/);
- if (pShareDataNode)
+ if (bUseShareMemWorkaround)
{
- IMG_BOOL freeIfNotUsed = (psAllocDeviceMemOUT->eError == PVRSRV_OK) ? IMG_FALSE : IMG_TRUE;
- BM_XProcFinishShareIndex(pShareDataNode, freeIfNotUsed);
+ PVR_ASSERT(ui32ShareIndex != 7654321);
+ BM_XProcWorkaroundUnsetShareIndex(ui32ShareIndex);
}
- /* End mutually exclusive region */
-
if(psAllocDeviceMemOUT->eError != PVRSRV_OK)
{
return 0;
}
- if (pShareDataNode)
+ psMemInfo->sShareMemWorkaround.bInUse = bUseShareMemWorkaround;
+ if (bUseShareMemWorkaround)
{
- psMemInfo->sShareMemWorkaround.bInUse = IMG_TRUE;
- psMemInfo->sShareMemWorkaround.pShareDataNode = pShareDataNode;
+ PVR_ASSERT(ui32ShareIndex != 7654321);
+ psMemInfo->sShareMemWorkaround.ui32ShareIndex = ui32ShareIndex;
psMemInfo->sShareMemWorkaround.hDevCookieInt = hDevCookieInt;
psMemInfo->sShareMemWorkaround.ui32OrigReqAttribs = psAllocDeviceMemIN->ui32Attribs;
psMemInfo->sShareMemWorkaround.ui32OrigReqSize = (IMG_UINT32)psAllocDeviceMemIN->ui32Size;
@@ -577,7 +722,7 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
psAllocDeviceMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
psAllocDeviceMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* see below */
#else
psAllocDeviceMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
#endif
@@ -608,7 +753,7 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
if(psAllocDeviceMemIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
{
-
+ /* signal no syncinfo */
OSMemSet(&psAllocDeviceMemOUT->sClientSyncInfo,
0,
sizeof (PVRSRV_CLIENT_SYNC_INFO));
@@ -616,7 +761,7 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
}
else
{
-
+ /* and setup the sync info */
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psAllocDeviceMemOUT->sClientSyncInfo.psSyncData =
@@ -625,6 +770,8 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psAllocDeviceMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psAllocDeviceMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
@@ -655,7 +802,6 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
psAllocDeviceMemOUT->sClientMemInfo.psClientSyncInfo =
&psAllocDeviceMemOUT->sClientSyncInfo;
-
}
COMMIT_HANDLE_BATCH_OR_ERROR(psAllocDeviceMemOUT->eError, psPerProc)
@@ -663,7 +809,7 @@ PVRSRVAllocDeviceMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-#endif
+#endif /* OS_PVRSRV_ALLOC_DEVICE_MEM_BW */
static IMG_INT
PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
@@ -674,7 +820,6 @@ PVRSRVFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
IMG_HANDLE hDevCookieInt;
IMG_VOID *pvKernelMemInfo;
-
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_FREE_DEVICEMEM);
psRetOUT->eError =
@@ -841,7 +986,7 @@ PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
ui32BridgeID == PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_EXPORT_DEVICEMEM_2));
PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
-
+ /* find the device cookie */
psExportDeviceMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevCookieInt,
@@ -854,7 +999,7 @@ PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* find the kernel meminfo from the process handle list */
psExportDeviceMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
(IMG_PVOID *)&psKernelMemInfo,
@@ -871,7 +1016,7 @@ PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* see if it's already exported */
psExportDeviceMemOUT->eError =
PVRSRVFindHandle(KERNEL_HANDLE_BASE,
&psExportDeviceMemOUT->hMemInfo,
@@ -879,12 +1024,12 @@ PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_HANDLE_TYPE_MEM_INFO);
if(psExportDeviceMemOUT->eError == PVRSRV_OK)
{
-
+ /* it's already exported */
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVExportDeviceMemBW: allocation is already exported"));
return 0;
}
-
+ /* export the allocation */
psExportDeviceMemOUT->eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
&psExportDeviceMemOUT->hMemInfo,
psKernelMemInfo,
@@ -896,7 +1041,7 @@ PVRSRVExportDeviceMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* mark the meminfo as 'exported' */
psKernelMemInfo->ui32Flags |= PVRSRV_MEM_EXPORTED;
return 0;
@@ -919,7 +1064,7 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
NEW_HANDLE_BATCH_OR_ERROR(psMapDevMemOUT->eError, psPerProc, 2)
-
+ /* lookup srcmeminfo handle */
psMapDevMemOUT->eError = PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
(IMG_VOID**)&psSrcKernelMemInfo,
psMapDevMemIN->hKernelMemInfo,
@@ -929,7 +1074,7 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* lookup dev mem heap handle */
psMapDevMemOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDstDevMemHeap,
psMapDevMemIN->hDstDevMemHeap,
@@ -939,21 +1084,21 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* check for workaround */
if (psSrcKernelMemInfo->sShareMemWorkaround.bInUse)
{
PVR_DPF((PVR_DBG_MESSAGE, "using the mem wrap workaround."));
-
-
-
-
-
-
-
- /* Start mutually exclusive region */
-
- psMapDevMemOUT->eError = BM_XProcSetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.pShareDataNode);
+ /* Ensure we get the same ID for this allocation, such that it
+ inherits the same physical block. Rather than add a lot of
+ plumbing to several APIs, we call into buffer manager directly
+ to set "global" state. This works only if we make
+ this allocation while holding the bridge mutex and don't
+ make any other allocations (because the state persists and
+ would affect other device memory allocations too). It is
+ important that we bracket the PVRSRVAllocDeviceMemKM() call
+ with this Set/Unset pair. */
+ psMapDevMemOUT->eError = BM_XProcWorkaroundSetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
if(psMapDevMemOUT->eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW(): failed to recycle shared buffer"));
@@ -967,28 +1112,32 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAttribs | PVRSRV_MEM_NO_SYNCOBJ,
psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqSize,
psSrcKernelMemInfo->sShareMemWorkaround.ui32OrigReqAlignment,
+ IMG_NULL,
+ 0,
+ /* FIXME: Do we need to be able to export sparse memory? */
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psDstKernelMemInfo,
- "" );
-
-
- BM_XProcFinishShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.pShareDataNode, IMG_FALSE);
+ "" /*FIXME: add something meaningful*/);
+ /* counterpart of the above "SetShareIndex". NB: this must be
+ done in both the success and failure paths of the
+ AllocDeviceMemKM() call */
+ BM_XProcWorkaroundUnsetShareIndex(psSrcKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
if(psMapDevMemOUT->eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "lakjgfgewjlrgebhe"));
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVMapDeviceMemoryBW: Failed to create allocation for cross-process memory map"));
return 0;
}
- /* End mutually exclusive region */
if(psSrcKernelMemInfo->psKernelSyncInfo)
{
- psSrcKernelMemInfo->psKernelSyncInfo->ui32RefCount++;
+ PVRSRVKernelSyncInfoIncRef(psSrcKernelMemInfo->psKernelSyncInfo, psSrcKernelMemInfo);
}
psDstKernelMemInfo->psKernelSyncInfo = psSrcKernelMemInfo->psKernelSyncInfo;
}
else
{
-
+ /* map the meminfo to the target heap and memory context */
psMapDevMemOUT->eError = PVRSRVMapDeviceMemoryKM(psPerProc,
psSrcKernelMemInfo,
hDstDevMemHeap,
@@ -999,7 +1148,7 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
}
}
-
+ /* copy the workaround info */
psDstKernelMemInfo->sShareMemWorkaround = psSrcKernelMemInfo->sShareMemWorkaround;
OSMemSet(&psMapDevMemOUT->sDstClientMemInfo,
@@ -1017,12 +1166,12 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
psMapDevMemOUT->sDstClientMemInfo.ui32Flags = psDstKernelMemInfo->ui32Flags;
psMapDevMemOUT->sDstClientMemInfo.uAllocSize = psDstKernelMemInfo->uAllocSize;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* see below */
#else
psMapDevMemOUT->sDstClientMemInfo.hMappingInfo = psDstKernelMemInfo->sMemBlk.hOSMemHandle;
#endif
-
+ /* allocate handle to the DST kernel meminfo */
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&psMapDevMemOUT->sDstClientMemInfo.hKernelMemInfo,
psDstKernelMemInfo,
@@ -1031,7 +1180,7 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo = IMG_NULL;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psDstKernelMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
@@ -1047,7 +1196,7 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
}
#endif
-
+ /* and setup the sync info */
if(psDstKernelMemInfo->psKernelSyncInfo)
{
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
@@ -1057,9 +1206,11 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
psDstKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psMapDevMemOUT->sDstClientSyncInfo.sReadOpsCompleteDevVAddr =
psDstKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapDevMemOUT->sDstClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psDstKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psDstKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
@@ -1080,7 +1231,11 @@ PVRSRVMapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
#endif
psMapDevMemOUT->sDstClientMemInfo.psClientSyncInfo = &psMapDevMemOUT->sDstClientSyncInfo;
-
+ /*
+ * The sync info is associated with the device buffer,
+ * and not allocated here. It isn't exported when created,
+ * hence the handle allocation rather than a lookup.
+ */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psMapDevMemOUT->sDstClientSyncInfo.hKernelSyncInfo,
psDstKernelMemInfo->psKernelSyncInfo,
@@ -1145,7 +1300,7 @@ PVRSRVUnmapDeviceMemoryBW(IMG_UINT32 ui32BridgeID,
}
else
{
- psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo);
+ psRetOUT->eError = PVRSRVUnmapDeviceMemoryKM(psKernelMemInfo, psPerProc);
if(psRetOUT->eError != PVRSRV_OK)
{
return 0;
@@ -1297,7 +1452,11 @@ PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
NEW_HANDLE_BATCH_OR_ERROR(psMapDevClassMemOUT->eError, psPerProc, 2)
-
+ /*
+ * The buffer to be mapped can belong to a 3rd party display or
+ * buffer driver, and we don't know which type we have at this
+ * point.
+ */
psMapDevClassMemOUT->eError =
PVRSRVLookupHandleAnyType(psPerProc->psHandleBase,
&hDeviceClassBufferInt,
@@ -1309,7 +1468,7 @@ PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* get the device memory context */
psMapDevClassMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
@@ -1321,7 +1480,7 @@ PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* Having looked up the handle, now check its type */
switch(eHandleType)
{
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
@@ -1388,7 +1547,7 @@ PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo = IMG_NULL;
-
+ /* and setup the sync info */
if(psMemInfo->psKernelSyncInfo)
{
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
@@ -1398,6 +1557,8 @@ PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psMapDevClassMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapDevClassMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != 0)
@@ -1420,7 +1581,12 @@ PVRSRVMapDeviceClassMemoryBW(IMG_UINT32 ui32BridgeID,
#endif
psMapDevClassMemOUT->sClientMemInfo.psClientSyncInfo = &psMapDevClassMemOUT->sClientSyncInfo;
-
+ /*
+ * The sync info is associated with the device buffer,
+ * and not allocated here. It isn't exported when
+ * created, hence the handle allocation rather than a
+ * lookup.
+ */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psMapDevClassMemOUT->sClientSyncInfo.hKernelSyncInfo,
psMemInfo->psKernelSyncInfo,
@@ -1483,7 +1649,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
PVRSRV_BRIDGE_OUT_WRAP_EXT_MEMORY *psWrapExtMemOUT,
PVRSRV_PER_PROCESS_DATA *psPerProc);
-#else
+#else /* OS_PVRSRV_WRAP_EXT_MEM_BW */
static IMG_INT
PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_WRAP_EXT_MEMORY *psWrapExtMemIN,
@@ -1500,7 +1666,10 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
NEW_HANDLE_BATCH_OR_ERROR(psWrapExtMemOUT->eError, psPerProc, 2)
-
+ /*
+ * FIXME: This needs reworking - don't use the user supplied page
+ * table list, get the list from the OS.
+ */
psWrapExtMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevCookieInt,
psWrapExtMemIN->hDevCookie,
@@ -1510,7 +1679,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* get the device memory context */
psWrapExtMemOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase, &hDevMemContextInt,
psWrapExtMemIN->hDevMemContext,
@@ -1539,7 +1708,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
ui32PageTableSize) != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32PageTableSize, (IMG_VOID *)psSysPAddr, 0);
-
+ /*not nulling pointer, out of scope*/
return -EFAULT;
}
}
@@ -1561,7 +1730,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
ui32PageTableSize,
(IMG_VOID *)psSysPAddr, 0);
-
+ /*not nulling pointer, out of scope*/
}
if(psWrapExtMemOUT->eError != PVRSRV_OK)
@@ -1572,12 +1741,13 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
psWrapExtMemOUT->sClientMemInfo.pvLinAddrKM =
psMemInfo->pvLinAddrKM;
-
+ /* setup the mem info */
psWrapExtMemOUT->sClientMemInfo.pvLinAddr = 0;
psWrapExtMemOUT->sClientMemInfo.sDevVAddr = psMemInfo->sDevVAddr;
psWrapExtMemOUT->sClientMemInfo.ui32Flags = psMemInfo->ui32Flags;
psWrapExtMemOUT->sClientMemInfo.uAllocSize = psMemInfo->uAllocSize;
#if defined (SUPPORT_SID_INTERFACE)
+/* see below */
#else
psWrapExtMemOUT->sClientMemInfo.hMappingInfo = psMemInfo->sMemBlk.hOSMemHandle;
#endif
@@ -1589,7 +1759,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
PVRSRV_HANDLE_ALLOC_FLAG_NONE);
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psMemInfo->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
@@ -1605,7 +1775,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
}
#endif
-
+ /* setup the sync info */
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psWrapExtMemOUT->sClientSyncInfo.psSyncData =
psMemInfo->psKernelSyncInfo->psSyncData;
@@ -1613,9 +1783,11 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
psMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psWrapExtMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psWrapExtMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* alloc subhandle for the mapping info */
if (psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
{
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
@@ -1648,7 +1820,7 @@ PVRSRVWrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-#endif
+#endif /* OS_PVRSRV_WRAP_EXT_MEM_BW */
static IMG_INT
PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
@@ -1685,6 +1857,169 @@ PVRSRVUnwrapExtMemoryBW(IMG_UINT32 ui32BridgeID,
return 0;
}
+#if defined(SUPPORT_ION)
+static IMG_INT
+PVRSRVMapIonHandleBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_MAP_ION_HANDLE *psMapIonIN,
+ PVRSRV_BRIDGE_OUT_MAP_ION_HANDLE *psMapIonOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ psMapIonOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psMapIonIN->hDevCookie,
+ psMapIonIN->hDevCookie,
+ PVRSRV_HANDLE_TYPE_DEV_NODE);
+ if (psMapIonOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup device node handle", __FUNCTION__));
+ return 0;
+ }
+
+ psMapIonOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &psMapIonIN->hDevMemContext,
+ psMapIonIN->hDevMemContext,
+ PVRSRV_HANDLE_TYPE_DEV_MEM_CONTEXT);
+ if (psMapIonOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to lookup memory context handle", __FUNCTION__));
+ return 0;
+ }
+
+ psMapIonOUT->eError = PVRSRVMapIonHandleKM(psPerProc,
+ psMapIonIN->hDevCookie,
+ psMapIonIN->hDevMemContext,
+ psMapIonIN->handle,
+ psMapIonIN->ui32Attribs,
+ psMapIonIN->ui32Size,
+ &psKernelMemInfo);
+ if (psMapIonOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to map ion handle", __FUNCTION__));
+ return 0;
+ }
+
+ OSMemSet(&psMapIonOUT->sClientMemInfo,
+ 0,
+ sizeof(psMapIonOUT->sClientMemInfo));
+
+ psMapIonOUT->sClientMemInfo.pvLinAddrKM =
+ psKernelMemInfo->pvLinAddrKM;
+
+ psMapIonOUT->sClientMemInfo.pvLinAddr = 0;
+ psMapIonOUT->sClientMemInfo.sDevVAddr = psKernelMemInfo->sDevVAddr;
+ psMapIonOUT->sClientMemInfo.ui32Flags = psKernelMemInfo->ui32Flags;
+ psMapIonOUT->sClientMemInfo.uAllocSize = psKernelMemInfo->uAllocSize;
+
+ /* No mapping info, we map through ion */
+ psMapIonOUT->sClientMemInfo.hMappingInfo = IMG_NULL;
+
+
+ PVRSRVAllocHandleNR(psPerProc->psHandleBase,
+ &psMapIonOUT->sClientMemInfo.hKernelMemInfo,
+ psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE);
+
+ if(psMapIonIN->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ)
+ {
+ /* signal no syncinfo */
+ OSMemSet(&psMapIonOUT->sClientSyncInfo,
+ 0,
+ sizeof (PVRSRV_CLIENT_SYNC_INFO));
+ psMapIonOUT->sClientMemInfo.psClientSyncInfo = IMG_NULL;
+ }
+ else
+ {
+ /* and setup the sync info */
+#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
+ psMapIonOUT->sClientSyncInfo.psSyncData =
+ psKernelMemInfo->psKernelSyncInfo->psSyncData;
+ psMapIonOUT->sClientSyncInfo.sWriteOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
+ psMapIonOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapIonOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ if (psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
+ {
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapIonOUT->sClientSyncInfo.hMappingInfo,
+ psMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapIonOUT->sClientMemInfo.hKernelMemInfo);
+ }
+ else
+ {
+ psMapIonOUT->sClientSyncInfo.hMappingInfo = 0;
+ }
+#else
+ psMapIonOUT->sClientSyncInfo.hMappingInfo =
+ psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle;
+#endif
+#endif
+
+ PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
+ &psMapIonOUT->sClientSyncInfo.hKernelSyncInfo,
+ psKernelMemInfo->psKernelSyncInfo,
+ PVRSRV_HANDLE_TYPE_SYNC_INFO,
+ PVRSRV_HANDLE_ALLOC_FLAG_NONE,
+ psMapIonOUT->sClientMemInfo.hKernelMemInfo);
+
+ psMapIonOUT->sClientMemInfo.psClientSyncInfo =
+ &psMapIonOUT->sClientSyncInfo;
+ }
+ return 0;
+}
+
+static IMG_INT
+PVRSRVUnmapIonHandleBW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_UNMAP_ION_HANDLE *psUnmapIonIN,
+ PVRSRV_BRIDGE_RETURN *psUnmapIonOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvKernelMemInfo;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_UNMAP_ION_HANDLE);
+
+ psUnmapIonOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvKernelMemInfo,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapIonIN->hKernelMemInfo,
+#else
+ psUnmapIonIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ if(psUnmapIonOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psUnmapIonOUT->eError = PVRSRVUnmapIonHandleKM(pvKernelMemInfo);
+
+ if(psUnmapIonOUT->eError != PVRSRV_OK)
+ {
+ return 0;
+ }
+
+ psUnmapIonOUT->eError =
+ PVRSRVReleaseHandle(psPerProc->psHandleBase,
+#if defined (SUPPORT_SID_INTERFACE)
+ psUnmapIonIN->hKernelMemInfo,
+#else
+ psUnmapIonIN->psKernelMemInfo,
+#endif
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+
+ return 0;
+}
+#endif /* SUPPORT_ION */
+
static IMG_INT
PVRSRVGetFreeDeviceMemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_GETFREEDEVICEMEM *psGetFreeDeviceMemIN,
@@ -1712,7 +2047,7 @@ PVRMMapOSMemHandleToMMapDataBW(IMG_UINT32 ui32BridgeID,
{
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_MHANDLE_TO_MMAP_DATA);
-#if defined (__linux__) || defined(__QNXNTO__)
+#if defined (__linux__) || defined (__QNXNTO__)
psMMapDataOUT->eError =
PVRMMapOSMemHandleToMMapData(psPerProc,
psMMapDataIN->hMHandle,
@@ -1738,7 +2073,7 @@ PVRMMapReleaseMMapDataBW(IMG_UINT32 ui32BridgeID,
{
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_RELEASE_MMAP_DATA);
-#if defined (__linux__) || defined(__QNXNTO__)
+#if defined (__linux__) || defined (__QNXNTO__)
psMMapDataOUT->eError =
PVRMMapReleaseMMapData(psPerProc,
psMMapDataIN->hMHandle,
@@ -2168,7 +2503,7 @@ PDumpSyncPolBW(IMG_UINT32 ui32BridgeID,
ui32Offset = offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
}
-
+ /* FIXME: Move this code to somewhere outside of the bridge */
if (psPDumpSyncPolIN->bUseLastOpDumpVal)
{
if(psPDumpSyncPolIN->bIsRead)
@@ -2287,7 +2622,7 @@ PDumpStopInitPhaseBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-#endif
+#endif /* PDUMP */
static IMG_INT
@@ -2302,6 +2637,7 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
PVRSRV_ERROR eError;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_GET_MISC_INFO);
+
#if defined (SUPPORT_SID_INTERFACE)
sMiscInfo.ui32StateRequest = psGetMiscInfoIN->sMiscInfo.ui32StateRequest;
sMiscInfo.ui32StatePresent = psGetMiscInfoIN->sMiscInfo.ui32StatePresent;
@@ -2311,8 +2647,10 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
OSMemCopy(&sMiscInfo.sCacheOpCtl,
&psGetMiscInfoIN->sMiscInfo.sCacheOpCtl,
sizeof(sMiscInfo.sCacheOpCtl));
+ OSMemCopy(&sMiscInfo.sGetRefCountCtl,
+ &psGetMiscInfoIN->sMiscInfo.sGetRefCountCtl,
+ sizeof(sMiscInfo.sGetRefCountCtl));
#else
-
OSMemCopy(&psGetMiscInfoOUT->sMiscInfo,
&psGetMiscInfoIN->sMiscInfo,
sizeof(PVRSRV_MISC_INFO));
@@ -2322,7 +2660,8 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) &&
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
{
-
+ /* Client must choose which of memstats and DDK version will be written to
+ * kernel side buffer */
psGetMiscInfoOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
@@ -2331,7 +2670,7 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0) ||
((psGetMiscInfoIN->sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0))
{
-
+ /* Alloc kernel side buffer to write into */
#if defined (SUPPORT_SID_INTERFACE)
ASSIGN_AND_EXIT_ON_ERROR(psGetMiscInfoOUT->eError,
OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
@@ -2340,7 +2679,7 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
"Output string buffer"));
psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&sMiscInfo);
-
+ /* Copy result to user */
eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
sMiscInfo.pszMemoryStr,
@@ -2354,14 +2693,14 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
psGetMiscInfoOUT->eError = PVRSRVGetMiscInfoKM(&psGetMiscInfoOUT->sMiscInfo);
-
+ /* Copy result to user */
eError = CopyToUserWrapper(psPerProc, ui32BridgeID,
psGetMiscInfoIN->sMiscInfo.pszMemoryStr,
psGetMiscInfoOUT->sMiscInfo.pszMemoryStr,
psGetMiscInfoOUT->sMiscInfo.ui32MemoryStrLen);
#endif
-
+ /* Free kernel side buffer again */
#if defined (SUPPORT_SID_INTERFACE)
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
sMiscInfo.ui32MemoryStrLen,
@@ -2372,12 +2711,16 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
(IMG_VOID *)psGetMiscInfoOUT->sMiscInfo.pszMemoryStr, 0);
#endif
-
+ /* Replace output buffer pointer with input pointer, as both are expected
+ * to point to the same userspace memory.
+ */
psGetMiscInfoOUT->sMiscInfo.pszMemoryStr = psGetMiscInfoIN->sMiscInfo.pszMemoryStr;
if(eError != PVRSRV_OK)
{
-
+ /* Do error check at the end as we always have to free and reset the
+ * pointer.
+ */
PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoBW Error copy to user"));
return -EFAULT;
}
@@ -2391,13 +2734,19 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
#endif
}
-
+ /* Return on error so exit status of PVRSRVGetMiscInfoKM is propagated to client.
+ * Don't alloc handles for event object or timer; if error exit status is returned
+ * the handles should not be used (even if not null) */
if (psGetMiscInfoOUT->eError != PVRSRV_OK)
{
return 0;
}
-
+ /*
+ * The handles are not allocated in batch mode as they are shared
+ * (a shared handle is allocated at most once), and there is no
+ * resource allocation to undo if the handle allocation fails.
+ */
#if defined (SUPPORT_SID_INTERFACE)
if (sMiscInfo.ui32StateRequest & PVRSRV_MISC_INFO_GLOBALEVENTOBJECT_PRESENT)
#else
@@ -2423,7 +2772,6 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sGlobalEventObject.szName,
sMiscInfo.sGlobalEventObject.szName,
EVENTOBJNAME_MAXLENGTH);
-
#endif
}
@@ -2433,7 +2781,7 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
if (psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle)
#endif
{
-
+ /* Allocate handle for SOC OSMemHandle */
psGetMiscInfoOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
&psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle,
#if defined (SUPPORT_SID_INTERFACE)
@@ -2455,7 +2803,7 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
psGetMiscInfoOUT->sMiscInfo.hSOCTimerRegisterOSMemHandle = 0;
}
-
+ /* copy data from local sMiscInfo to OUT */
psGetMiscInfoOUT->sMiscInfo.ui32StateRequest = sMiscInfo.ui32StateRequest;
psGetMiscInfoOUT->sMiscInfo.ui32StatePresent = sMiscInfo.ui32StatePresent;
@@ -2471,6 +2819,9 @@ PVRSRVGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sCacheOpCtl,
&sMiscInfo.sCacheOpCtl,
sizeof(psGetMiscInfoOUT->sMiscInfo.sCacheOpCtl));
+ OSMemCopy(&psGetMiscInfoOUT->sMiscInfo.sGetRefCountCtl,
+ &sMiscInfo.sGetRefCountCtl,
+ sizeof(psGetMiscInfoOUT->sMiscInfo.sGetRefCountCtl));
#endif
return 0;
@@ -2485,19 +2836,27 @@ PVRSRVConnectBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_CONNECT_SERVICES);
#if defined(PDUMP)
-
+ /* Store the per process connection info.
+ * The Xserver initially connects via PVR2D which sets the persistent flag.
+ * But, later the Xserver may connect via SGL which doesn't carry the flag (in
+ * general SGL clients aren't persistent). So we OR in the flag so if it was set
+ * before it remains set.
+ */
if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PERSIST) != 0)
{
psPerProc->bPDumpPersistent = IMG_TRUE;
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Select whether this client is our 'active' target for pdumping in a
+ * multi-process environment.
+ * NOTE: only 1 active target is supported at present.
+ */
if ((psConnectServicesIN->ui32Flags & SRV_FLAGS_PDUMP_ACTIVE) != 0)
{
psPerProc->bPDumpActive = IMG_TRUE;
}
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
#else
PVR_UNREFERENCED_PARAMETER(psConnectServicesIN);
#endif
@@ -2518,7 +2877,7 @@ PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_DISCONNECT_SERVICES);
-
+ /* just return OK, per-process data is cleaned up by resmgr */
psRetOUT->eError = PVRSRV_OK;
return 0;
@@ -2526,18 +2885,18 @@ PVRSRVDisconnectBW(IMG_UINT32 ui32BridgeID,
static IMG_INT
PVRSRVEnumerateDCBW(IMG_UINT32 ui32BridgeID,
- PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
- PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
- PVRSRV_PER_PROCESS_DATA *psPerProc)
+ PVRSRV_BRIDGE_IN_ENUMCLASS *psEnumDispClassIN,
+ PVRSRV_BRIDGE_OUT_ENUMCLASS *psEnumDispClassOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
{
PVR_UNREFERENCED_PARAMETER(psPerProc);
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_ENUM_CLASS);
- psEnumDispClassOUT->eError =
- PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
- &psEnumDispClassOUT->ui32NumDevices,
- &psEnumDispClassOUT->ui32DevID[0]);
+ psEnumDispClassOUT->eError =
+ PVRSRVEnumerateDCKM(psEnumDispClassIN->sDeviceClass,
+ &psEnumDispClassOUT->ui32NumDevices,
+ &psEnumDispClassOUT->ui32DevID[0]);
return 0;
}
@@ -2607,7 +2966,7 @@ PVRSRVCloseDCDeviceBW(IMG_UINT32 ui32BridgeID,
return 0;
}
- psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt, IMG_FALSE);
+ psRetOUT->eError = PVRSRVCloseDCDeviceKM(pvDispClassInfoInt);
if(psRetOUT->eError != PVRSRV_OK)
{
return 0;
@@ -2678,9 +3037,10 @@ PVRSRVEnumDCDimsBW(IMG_UINT32 ui32BridgeID,
return 0;
}
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
static IMG_INT
PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
- PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN,
+ PVRSRV_BRIDGE_IN_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferIN, //IMG_HANDLE *phGetDispClassSysBufferIN,
PVRSRV_BRIDGE_OUT_GET_DISPCLASS_SYSBUFFER *psGetDispClassSysBufferOUT,
PVRSRV_PER_PROCESS_DATA *psPerProc)
{
@@ -2710,7 +3070,7 @@ PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* PRQA S 1461 6 */ /* ignore warning about enum type being converted */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psGetDispClassSysBufferOUT->hBuffer,
hBufferInt,
@@ -2722,6 +3082,7 @@ PVRSRVGetDCSystemBufferBW(IMG_UINT32 ui32BridgeID,
return 0;
}
+#endif
static IMG_INT
PVRSRVGetDCInfoBW(IMG_UINT32 ui32BridgeID,
@@ -2775,7 +3136,7 @@ PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* Get ui32SwapChainID from input */
ui32SwapChainID = psCreateDispClassSwapChainIN->ui32SwapChainID;
psCreateDispClassSwapChainOUT->eError =
@@ -2793,7 +3154,7 @@ PVRSRVCreateDCSwapChainBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* Pass ui32SwapChainID to output */
psCreateDispClassSwapChainOUT->ui32SwapChainID = ui32SwapChainID;
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
@@ -3054,10 +3415,11 @@ PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
pvSwapChain,
&psGetDispClassBuffersOUT->ui32BufferCount,
#if defined (SUPPORT_SID_INTERFACE)
- pahBuffer);
+ pahBuffer,
#else
- psGetDispClassBuffersOUT->ahBuffer);
+ psGetDispClassBuffersOUT->ahBuffer,
#endif
+ psGetDispClassBuffersOUT->asPhyAddr);
if (psGetDispClassBuffersOUT->eError != PVRSRV_OK)
{
return 0;
@@ -3073,7 +3435,7 @@ PVRSRVGetDCBuffersBW(IMG_UINT32 ui32BridgeID,
IMG_HANDLE hBufferExt;
#endif
-
+ /* PRQA S 1461 15 */ /* ignore warning about enum type being converted */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&hBufferExt,
@@ -3159,7 +3521,6 @@ PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
}
#endif
-
psRetOUT->eError =
PVRSRVSwapToDCBufferKM(pvDispClassInfo,
pvSwapChainBuf,
@@ -3176,6 +3537,136 @@ PVRSRVSwapToDCBufferBW(IMG_UINT32 ui32BridgeID,
}
static IMG_INT
+PVRSRVSwapToDCBuffer2BW(IMG_UINT32 ui32BridgeID,
+ PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_BUFFER2 *psSwapDispClassBufferIN,
+ PVRSRV_BRIDGE_RETURN *psRetOUT,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
+{
+ IMG_VOID *pvPrivData = IMG_NULL;
+ IMG_VOID *pvDispClassInfo;
+ IMG_VOID *pvSwapChain;
+ IMG_UINT32 i;
+
+ PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2);
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ &pvDispClassInfo,
+ psSwapDispClassBufferIN->hDeviceKM,
+ PVRSRV_HANDLE_TYPE_DISP_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_INFO handle"));
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupSubHandle(psPerProc->psHandleBase,
+ &pvSwapChain,
+ psSwapDispClassBufferIN->hSwapChain,
+ PVRSRV_HANDLE_TYPE_DISP_SWAP_CHAIN,
+ psSwapDispClassBufferIN->hDeviceKM);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up DISP_BUFFER handle"));
+ return 0;
+ }
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psSwapDispClassBufferIN->ppsKernelMemInfos,
+ sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelMemInfos"));
+ return -EFAULT;
+ }
+
+ if(!OSAccessOK(PVR_VERIFY_WRITE,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos,
+ sizeof(IMG_HANDLE) * psSwapDispClassBufferIN->ui32NumMemInfos))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Access check failed for ppsKernelSyncInfos"));
+ return -EFAULT;
+ }
+
+ for (i = 0; i < psSwapDispClassBufferIN->ui32NumMemInfos; i++)
+ {
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psSwapDispClassBufferIN->ppsKernelMemInfos[i],
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up MEM_INFO handle"));
+ return 0;
+ }
+
+ psRetOUT->eError =
+ PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelSyncInfo,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos[i],
+ PVRSRV_HANDLE_TYPE_SYNC_INFO);
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to look up SYNC_INFO handle"));
+ return 0;
+ }
+
+ psSwapDispClassBufferIN->ppsKernelMemInfos[i] = psKernelMemInfo;
+ psSwapDispClassBufferIN->ppsKernelSyncInfos[i] = psKernelSyncInfo;
+ }
+
+ if(psSwapDispClassBufferIN->ui32PrivDataLength > 0)
+ {
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ (IMG_VOID **)&pvPrivData, IMG_NULL,
+ "Swap Command Private Data") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2BW: Failed to allocate private data space"));
+ return -ENOMEM;
+ }
+
+ if(CopyFromUserWrapper(psPerProc,
+ ui32BridgeID,
+ pvPrivData,
+ psSwapDispClassBufferIN->pvPrivData,
+ psSwapDispClassBufferIN->ui32PrivDataLength) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVSwapToDCBuffer2BW: Failed to copy private data"));
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ pvPrivData, IMG_NULL);
+ return -EFAULT;
+ }
+ }
+
+ psRetOUT->eError =
+ PVRSRVSwapToDCBuffer2KM(pvDispClassInfo,
+ pvSwapChain,
+ psSwapDispClassBufferIN->ui32SwapInterval,
+ psSwapDispClassBufferIN->ppsKernelMemInfos,
+ psSwapDispClassBufferIN->ppsKernelSyncInfos,
+ psSwapDispClassBufferIN->ui32NumMemInfos,
+ pvPrivData,
+ psSwapDispClassBufferIN->ui32PrivDataLength);
+
+ if(psRetOUT->eError != PVRSRV_OK)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ psSwapDispClassBufferIN->ui32PrivDataLength,
+ pvPrivData, IMG_NULL);
+ }
+
+ return 0;
+}
+
+
+
+static IMG_INT
PVRSRVSwapToDCSystemBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_SWAP_DISPCLASS_TO_SYSTEM *psSwapDispClassSystemIN,
PVRSRV_BRIDGE_RETURN *psRetOUT,
@@ -3278,7 +3769,7 @@ PVRSRVCloseBCDeviceBW(IMG_UINT32 ui32BridgeID,
}
psRetOUT->eError =
- PVRSRVCloseBCDeviceKM(pvBufClassInfo, IMG_FALSE);
+ PVRSRVCloseBCDeviceKM(pvBufClassInfo);
if(psRetOUT->eError != PVRSRV_OK)
{
@@ -3351,7 +3842,7 @@ PVRSRVGetBCBufferBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* PRQA S 1461 6 */ /* ignore warning about enum type being converted */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psGetBufferClassBufferOUT->hBuffer,
hBufferInt,
@@ -3521,7 +4012,11 @@ PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /*
+ * To prevent the building up of deep chains of subhandles, parent
+ * the new meminfo off the parent of the input meminfo, if it has
+ * a parent.
+ */
psMapMemInfoMemOUT->eError =
PVRSRVGetParentHandle(psPerProc->psHandleBase,
&hParent,
@@ -3581,14 +4076,14 @@ PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
if(psKernelMemInfo->ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)
{
-
+ /* signal no syncinfo */
OSMemSet(&psMapMemInfoMemOUT->sClientSyncInfo,
0,
sizeof (PVRSRV_CLIENT_SYNC_INFO));
}
else
{
-
+ /* and setup the sync info */
#if !defined(PVRSRV_DISABLE_UM_SYNCOBJ_MAPPINGS)
psMapMemInfoMemOUT->sClientSyncInfo.psSyncData =
psKernelMemInfo->psKernelSyncInfo->psSyncData;
@@ -3596,6 +4091,8 @@ PVRSRVMapMemInfoMemBW(IMG_UINT32 ui32BridgeID,
psKernelMemInfo->psKernelSyncInfo->sWriteOpsCompleteDevVAddr;
psMapMemInfoMemOUT->sClientSyncInfo.sReadOpsCompleteDevVAddr =
psKernelMemInfo->psKernelSyncInfo->sReadOpsCompleteDevVAddr;
+ psMapMemInfoMemOUT->sClientSyncInfo.sReadOps2CompleteDevVAddr =
+ psKernelMemInfo->psKernelSyncInfo->sReadOps2CompleteDevVAddr;
#if defined (SUPPORT_SID_INTERFACE)
if (psKernelMemInfo->psKernelSyncInfo->psSyncDataMemInfoKM->sMemBlk.hOSMemHandle != IMG_NULL)
@@ -3660,13 +4157,25 @@ DummyBW(IMG_UINT32 ui32BridgeID,
}
+/*!
+ * *****************************************************************************
+ * @brief A wrapper for filling in the g_BridgeDispatchTable array that does
+ * error checking.
+ *
+ * @param ui32Index
+ * @param pszIOCName
+ * @param pfFunction
+ * @param pszFunctionName
+ *
+ * @return
+ ********************************************************************************/
IMG_VOID
_SetDispatchTableEntry(IMG_UINT32 ui32Index,
const IMG_CHAR *pszIOCName,
BridgeWrapperFunction pfFunction,
const IMG_CHAR *pszFunctionName)
{
- static IMG_UINT32 ui32PrevIndex = ~0UL;
+ static IMG_UINT32 ui32PrevIndex = ~0UL; /* -1 */
#if !defined(DEBUG)
PVR_UNREFERENCED_PARAMETER(pszIOCName);
#endif
@@ -3675,11 +4184,16 @@ _SetDispatchTableEntry(IMG_UINT32 ui32Index,
#endif
#if defined(DEBUG_BRIDGE_KM_DISPATCH_TABLE)
-
+ /* INTEGRATION_POINT: Enable this to dump out the dispatch table entries */
PVR_DPF((PVR_DBG_WARNING, "%s: %d %s %s", __FUNCTION__, ui32Index, pszIOCName, pszFunctionName));
#endif
-
+ /* We should never be over-writing a previous entry.
+ * If we are, tell the world about it.
+ * NOTE: This shouldn't be debug only since switching from debug->release
+ * etc is likly to modify the available ioctls and thus be a point where
+ * mistakes are exposed. This isn't run at at a performance critical time.
+ */
if(g_BridgeDispatchTable[ui32Index].pfFunction)
{
#if defined(DEBUG_BRIDGE_KM)
@@ -3694,7 +4208,17 @@ _SetDispatchTableEntry(IMG_UINT32 ui32Index,
PVR_DPF((PVR_DBG_ERROR, "NOTE: Enabling DEBUG_BRIDGE_KM_DISPATCH_TABLE may help debug this issue."));
}
-
+ /* Any gaps are sub-optimal in-terms of memory usage, but we are mainly
+ * interested in spotting any large gap of wasted memory that could be
+ * accidentally introduced.
+ *
+ * This will currently flag up any gaps > 5 entries.
+ *
+ * NOTE: This shouldn't be debug only since switching from debug->release
+ * etc is likly to modify the available ioctls and thus be a point where
+ * mistakes are exposed. This isn't run at at a performance critical time.
+ */
+// if((ui32PrevIndex != (IMG_UINT32)-1) &&
if((ui32PrevIndex != ~0UL) &&
((ui32Index >= ui32PrevIndex + DISPATCH_TABLE_GAP_THRESHOLD) ||
(ui32Index <= ui32PrevIndex)))
@@ -3734,14 +4258,14 @@ PVRSRVInitSrvConnectBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_INITSRV_CONNECT);
PVR_UNREFERENCED_PARAMETER(psBridgeIn);
-
+ /* PRQA S 3415 1 */ /* side effects needed - if any step fails */
if((OSProcHasPrivSrvInit() == IMG_FALSE) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RUNNING) || PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_RAN))
{
psRetOUT->eError = PVRSRV_ERROR_SRV_CONNECT_FAILED;
return 0;
}
-#if defined (__linux__) || defined(__QNXNTO__)
+#if defined (__linux__) || defined (__QNXNTO__)
PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_RUNNING, IMG_TRUE);
#endif
psPerProc->bInitProcess = IMG_TRUE;
@@ -3853,6 +4377,8 @@ PVRSRVEventObjectOpenBW(IMG_UINT32 ui32BridgeID,
}
#if defined (SUPPORT_SID_INTERFACE)
+/* Windows7, WinXP and Vista already use an Index type handle which the client glue uses directly */
+/* Linux requires a SID handle */
#if !defined (WINXP) && !defined(SUPPORT_VISTA)
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&psEventObjectOpenOUT->hOSEvent,
@@ -3917,7 +4443,7 @@ PVRSRVEventObjectCloseBW(IMG_UINT32 ui32BridgeID,
&psEventObjectCloseIN->sEventObject.szName,
EVENTOBJNAME_MAXLENGTH) != PVRSRV_OK)
{
-
+ /*not nulling pointer, out of scope*/
return -EFAULT;
}
@@ -3937,42 +4463,55 @@ typedef struct _MODIFY_SYNC_OP_INFO
IMG_UINT32 ui32ModifyFlags;
IMG_UINT32 ui32ReadOpsPendingSnapShot;
IMG_UINT32 ui32WriteOpsPendingSnapShot;
+ IMG_UINT32 ui32ReadOps2PendingSnapShot;
} MODIFY_SYNC_OP_INFO;
static PVRSRV_ERROR DoQuerySyncOpsSatisfied(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
IMG_UINT32 ui32ReadOpsPendingSnapShot,
- IMG_UINT32 ui32WriteOpsPendingSnapShot)
+ IMG_UINT32 ui32WriteOpsPendingSnapShot,
+ IMG_UINT32 ui32ReadOps2PendingSnapShot)
{
IMG_UINT32 ui32WriteOpsPending;
IMG_UINT32 ui32ReadOpsPending;
+ IMG_UINT32 ui32ReadOps2Pending;
+
+ /*
+ *
+ * We wait until the complete count reaches _or_moves_past_ the
+ * snapshot value.
+ *
+ */
-
if (!psKernelSyncInfo)
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
-
-
-
-
-
-
+ /*
+ let p be the pending ops count
+ let c be the complete ops count
+ let p' be the previously taken snapshot
+ if p exceeds c by an amount greater than that by which
+ p exceeds p', then the condition is not yet satisfied.
+ Note that (p - c) can never be negative, and neither can (p - p')
+ so we can do the comparison using unsigned arithmetic
+ */
ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
+ ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
if((ui32WriteOpsPending - ui32WriteOpsPendingSnapShot >=
ui32WriteOpsPending - psKernelSyncInfo->psSyncData->ui32WriteOpsComplete) &&
(ui32ReadOpsPending - ui32ReadOpsPendingSnapShot >=
- ui32ReadOpsPending - psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
+ ui32ReadOpsPending - psKernelSyncInfo->psSyncData->ui32ReadOpsComplete) &&
+ (ui32ReadOps2Pending - ui32ReadOps2PendingSnapShot >=
+ ui32ReadOps2Pending - psKernelSyncInfo->psSyncData->ui32ReadOps2Complete))
{
#if defined(PDUMP) && !defined(SUPPORT_VGX)
-
+ /* pdump the sync pol: reads */
PDumpComment("Poll for read ops complete to reach value (pdump: %u, actual snapshot: %u)",
psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
ui32ReadOpsPendingSnapShot);
@@ -3980,11 +4519,11 @@ static PVRSRV_ERROR DoQuerySyncOpsSatisfied(PVRSRV_KERNEL_SYNC_INFO *psKernelSyn
offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete),
psKernelSyncInfo->psSyncData->ui32LastReadOpDumpVal,
0xFFFFFFFF,
- PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_POLL_OPERATOR_EQUAL, /* * see "NB" below */
0,
MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
-
+ /* pdump the sync pol: writes */
PDumpComment("Poll for write ops complete to reach value (pdump: %u, actual snapshot: %u)",
psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
ui32WriteOpsPendingSnapShot);
@@ -3992,11 +4531,12 @@ static PVRSRV_ERROR DoQuerySyncOpsSatisfied(PVRSRV_KERNEL_SYNC_INFO *psKernelSyn
offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete),
psKernelSyncInfo->psSyncData->ui32LastOpDumpVal,
0xFFFFFFFF,
- PDUMP_POLL_OPERATOR_EQUAL,
+ PDUMP_POLL_OPERATOR_EQUAL, /* * see "NB" below */
0,
MAKEUNIQUETAG(psKernelSyncInfo->psSyncDataMemInfoKM));
-
-
+ /* NB: FIXME -- really need to POL on an expression to
+ accurately reflect the condition we need to check. How to
+ do this in PDUMP? */
#endif
return PVRSRV_OK;
}
@@ -4018,20 +4558,21 @@ static PVRSRV_ERROR DoModifyCompleteSyncOps(MODIFY_SYNC_OP_INFO *psModSyncOpInfo
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* If user has used the API correctly, we will always have reached the pending snapshot.
+ We should catch this error on the client side of the bridge and report it in an obvious way */
if((psModSyncOpInfo->ui32WriteOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32WriteOpsComplete)
|| (psModSyncOpInfo->ui32ReadOpsPendingSnapShot != psKernelSyncInfo->psSyncData->ui32ReadOpsComplete))
{
return PVRSRV_ERROR_BAD_SYNC_STATE;
}
-
+ /* update the WOpComplete */
if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
{
psKernelSyncInfo->psSyncData->ui32WriteOpsComplete++;
}
-
+ /* update the ROpComplete */
if(psModSyncOpInfo->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_RO_INC)
{
psKernelSyncInfo->psSyncData->ui32ReadOpsComplete++;
@@ -4060,12 +4601,12 @@ static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID pvParam,
if (psModSyncOpInfo->psKernelSyncInfo)
{
-
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
{
if (DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
- psModSyncOpInfo->ui32WriteOpsPendingSnapShot) == PVRSRV_OK)
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot) == PVRSRV_OK)
{
goto OpFlushedComplete;
}
@@ -4077,21 +4618,22 @@ static PVRSRV_ERROR ModifyCompleteSyncOpsCallBack(IMG_PVOID pvParam,
PVR_DPF((PVR_DBG_ERROR, " Write ops pending snapshot = %d, write ops complete = %d",
psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32WriteOpsComplete));
- PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, write ops complete = %d",
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, read ops complete = %d",
psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOpsComplete));
-
+ PVR_DPF((PVR_DBG_ERROR, " Read ops pending snapshot = %d, read ops2 complete = %d",
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot,
+ psModSyncOpInfo->psKernelSyncInfo->psSyncData->ui32ReadOps2Complete));
return PVRSRV_ERROR_TIMEOUT;
OpFlushedComplete:
-
DoModifyCompleteSyncOps(psModSyncOpInfo);
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MODIFY_SYNC_OP_INFO), (IMG_VOID *)psModSyncOpInfo, 0);
-
-
+ /* re-kick all services managed devices */
PVRSRVScheduleDeviceCallbacks();
return PVRSRV_OK;
@@ -4118,7 +4660,7 @@ PVRSRVCreateSyncInfoModObjBW(IMG_UINT32
(IMG_VOID **)&psModSyncOpInfo, 0,
"ModSyncOpInfo (MODIFY_SYNC_OP_INFO)"));
- psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
+ psModSyncOpInfo->psKernelSyncInfo = IMG_NULL; /* mark it as empty */
psCreateSyncInfoModObjOUT->eError = PVRSRVAllocHandle(psPerProc->psHandleBase,
&psCreateSyncInfoModObjOUT->hKernelSyncInfoModObj,
@@ -4165,11 +4707,13 @@ PVRSRVDestroySyncInfoModObjBW(IMG_UINT32
if(psModSyncOpInfo->psKernelSyncInfo != IMG_NULL)
{
-
+ /* Not empty */
psDestroySyncInfoModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
+
psDestroySyncInfoModObjOUT->eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psDestroySyncInfoModObjIN->hKernelSyncInfoModObj,
PVRSRV_HANDLE_TYPE_SYNC_INFO_MOD_OBJ);
@@ -4224,22 +4768,33 @@ PVRSRVModifyPendingSyncOpsBW(IMG_UINT32 ui32BridgeID,
if(psModSyncOpInfo->psKernelSyncInfo)
{
-
+ /* SyncInfoModification is not empty */
psModifySyncOpsOUT->eError = PVRSRV_ERROR_RETRY;
PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo Modification object is not empty"));
return 0;
}
-
+ /* Should never happen, but check to be sure */
+ if (psKernelSyncInfo == IMG_NULL)
+ {
+ psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
+ PVR_DPF((PVR_DBG_VERBOSE, "PVRSRVModifyPendingSyncOpsBW: SyncInfo bad handle"));
+ return 0;
+ }
+
+ PVRSRVKernelSyncInfoIncRef(psKernelSyncInfo, IMG_NULL);
+ /* setup info to store in resman */
psModSyncOpInfo->psKernelSyncInfo = psKernelSyncInfo;
psModSyncOpInfo->ui32ModifyFlags = psModifySyncOpsIN->ui32ModifyFlags;
psModSyncOpInfo->ui32ReadOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
psModSyncOpInfo->ui32WriteOpsPendingSnapShot = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
-
+ /* We return PRE-INCREMENTED versions of all sync Op Values */
psModifySyncOpsOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
psModifySyncOpsOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psModifySyncOpsOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
if(psModifySyncOpsIN->ui32ModifyFlags & PVRSRV_MODIFYSYNCOPS_FLAGS_WO_INC)
{
@@ -4251,7 +4806,7 @@ PVRSRVModifyPendingSyncOpsBW(IMG_UINT32 ui32BridgeID,
psKernelSyncInfo->psSyncData->ui32ReadOpsPending++;
}
-
+ /* pull the resman item to the front of the list */
psModifySyncOpsOUT->eError = ResManDissociateRes(psModSyncOpInfo->hResItem,
psPerProc->hResManContext);
@@ -4287,7 +4842,7 @@ PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32 ui32BridgeID,
if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
{
-
+ /* Empty */
psModifySyncOpsOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
@@ -4300,9 +4855,10 @@ PVRSRVModifyCompleteSyncOpsBW(IMG_UINT32 ui32BridgeID,
return 0;
}
+ PVRSRVKernelSyncInfoDecRef(psModSyncOpInfo->psKernelSyncInfo, IMG_NULL);
psModSyncOpInfo->psKernelSyncInfo = IMG_NULL;
-
+ /* re-kick all services managed devices */
PVRSRVScheduleDeviceCallbacks();
return 0;
@@ -4329,10 +4885,11 @@ PVRSRVSyncOpsTakeTokenBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* We return PRE-INCREMENTED versions of all sync Op Values */
psSyncOpsTakeTokenOUT->ui32ReadOpsPending = psKernelSyncInfo->psSyncData->ui32ReadOpsPending;
psSyncOpsTakeTokenOUT->ui32WriteOpsPending = psKernelSyncInfo->psSyncData->ui32WriteOpsPending;
+ psSyncOpsTakeTokenOUT->ui32ReadOps2Pending = psKernelSyncInfo->psSyncData->ui32ReadOps2Pending;
return 0;
}
@@ -4347,6 +4904,7 @@ PVRSRVSyncOpsFlushToTokenBW(IMG_UINT32 u
PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo;
IMG_UINT32 ui32ReadOpsPendingSnapshot;
IMG_UINT32 ui32WriteOpsPendingSnapshot;
+ IMG_UINT32 ui32ReadOps2PendingSnapshot;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SYNC_OPS_FLUSH_TO_TOKEN);
@@ -4362,10 +4920,12 @@ PVRSRVSyncOpsFlushToTokenBW(IMG_UINT32 u
ui32ReadOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOpsPendingSnapshot;
ui32WriteOpsPendingSnapshot = psSyncOpsFlushToTokenIN->ui32WriteOpsPendingSnapshot;
+ ui32ReadOps2PendingSnapshot = psSyncOpsFlushToTokenIN->ui32ReadOps2PendingSnapshot;
psSyncOpsFlushToTokenOUT->eError = DoQuerySyncOpsSatisfied(psKernelSyncInfo,
ui32ReadOpsPendingSnapshot,
- ui32WriteOpsPendingSnapshot);
+ ui32WriteOpsPendingSnapshot,
+ ui32ReadOps2PendingSnapshot);
if (psSyncOpsFlushToTokenOUT->eError != PVRSRV_OK && psSyncOpsFlushToTokenOUT->eError != PVRSRV_ERROR_RETRY)
{
@@ -4399,14 +4959,15 @@ PVRSRVSyncOpsFlushToModObjBW(IMG_UINT32
if(psModSyncOpInfo->psKernelSyncInfo == IMG_NULL)
{
-
+ /* Empty */
psSyncOpsFlushToModObjOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
}
psSyncOpsFlushToModObjOUT->eError = DoQuerySyncOpsSatisfied(psModSyncOpInfo->psKernelSyncInfo,
psModSyncOpInfo->ui32ReadOpsPendingSnapShot,
- psModSyncOpInfo->ui32WriteOpsPendingSnapShot);
+ psModSyncOpInfo->ui32WriteOpsPendingSnapShot,
+ psModSyncOpInfo->ui32ReadOps2PendingSnapShot);
if (psSyncOpsFlushToModObjOUT->eError != PVRSRV_OK && psSyncOpsFlushToModObjOUT->eError != PVRSRV_ERROR_RETRY)
{
@@ -4440,14 +5001,16 @@ PVRSRVSyncOpsFlushToDeltaBW(IMG_UINT32 u
return 0;
}
-
+ /* FIXME: there's logic here in the bridge-wrapper - this needs to be moved to
+ a better place */
+
ui32DeltaRead = psSyncInfo->psSyncData->ui32ReadOpsPending - psSyncInfo->psSyncData->ui32ReadOpsComplete;
ui32DeltaWrite = psSyncInfo->psSyncData->ui32WriteOpsPending - psSyncInfo->psSyncData->ui32WriteOpsComplete;
if (ui32DeltaRead <= psSyncOpsFlushToDeltaIN->ui32Delta && ui32DeltaWrite <= psSyncOpsFlushToDeltaIN->ui32Delta)
{
#if defined(PDUMP) && !defined(SUPPORT_VGX)
-
+ /* pdump the sync pol: reads */
PDumpComment("Poll for read ops complete to delta (%u)",
psSyncOpsFlushToDeltaIN->ui32Delta);
psSyncOpsFlushToDeltaOUT->eError =
@@ -4459,7 +5022,7 @@ PVRSRVSyncOpsFlushToDeltaBW(IMG_UINT32 u
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /* pdump the sync pol: writes */
PDumpComment("Poll for write ops complete to delta (%u)",
psSyncOpsFlushToDeltaIN->ui32Delta);
psSyncOpsFlushToDeltaOUT->eError =
@@ -4489,18 +5052,13 @@ FreeSyncInfoCallback(IMG_PVOID pvParam,
IMG_BOOL bDummy)
{
PVRSRV_KERNEL_SYNC_INFO *psSyncInfo;
- PVRSRV_ERROR eError;
PVR_UNREFERENCED_PARAMETER(ui32Param);
PVR_UNREFERENCED_PARAMETER(bDummy);
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)pvParam;
- eError = PVRSRVFreeSyncInfoKM(psSyncInfo);
- if (eError != PVRSRV_OK)
- {
- return eError;
- }
+ PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
return PVRSRV_OK;
}
@@ -4558,16 +5116,16 @@ PVRSRVAllocSyncInfoBW(IMG_UINT32 ui32Bri
0,
FreeSyncInfoCallback);
-
+ /* Success */
goto allocsyncinfo_commit;
-
+ /* Error handling */
allocsyncinfo_errorexit_freesyncinfo:
- PVRSRVFreeSyncInfoKM(psSyncInfo);
+ PVRSRVKernelSyncInfoDecRef(psSyncInfo, IMG_NULL);
allocsyncinfo_errorexit:
-
+ /* Common exit */
allocsyncinfo_commit:
psAllocSyncInfoOUT->eError = eError;
COMMIT_HANDLE_BATCH_OR_ERROR(eError, psPerProc);
@@ -4662,30 +5220,35 @@ CommonBridgeInit(IMG_VOID)
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
SetDispatchTableEntry(PVRSRV_BRIDGE_IMPORT_GEM, PVRSRVImportGEMBW);
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
-
- SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
- SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
- SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+#if defined(SUPPORT_ION)
+ SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_ION_HANDLE, PVRSRVMapIonHandleBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAP_ION_HANDLE, PVRSRVUnmapIonHandleBW);
+#endif
-
+ /* SIM */
+ SetDispatchTableEntry(PVRSRV_BRIDGE_PROCESS_SIMISR_EVENT, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_REGISTER_SIM_PROCESS, DummyBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_UNREGISTER_SIM_PROCESS, DummyBW);
+
+ /* User Mapping */
SetDispatchTableEntry(PVRSRV_BRIDGE_MAPPHYSTOUSERSPACE, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_UNMAPPHYSTOUSERSPACE, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GETPHYSTOUSERSPACEMAP, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_FB_STATS, DummyBW);
-
+ /* API to retrieve misc. info. from services */
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_MISC_INFO, PVRSRVGetMiscInfoBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_RELEASE_MISC_INFO, DummyBW);
-
+ /* Overlay ioctls */
#if defined (SUPPORT_OVERLAY_ROTATE_BLIT)
SetDispatchTableEntry(PVRSRV_BRIDGE_INIT_3D_OVL_BLT_RES, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_DEINIT_3D_OVL_BLT_RES, DummyBW);
#endif
-
+ /* PDUMP */
#if defined(PDUMP)
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_INIT, DummyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_MEMPOL, PDumpMemPolBW);
@@ -4705,20 +5268,24 @@ CommonBridgeInit(IMG_VOID)
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_CYCLE_COUNT_REG_READ, PDumpCycleCountRegReadBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STARTINITPHASE, PDumpStartInitPhaseBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_PDUMP_STOPINITPHASE, PDumpStopInitPhaseBW);
-#endif
+#endif /* defined(PDUMP) */
-
+ /* DisplayClass APIs */
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_OEMJTABLE, DummyBW);
-
+ /* device class enum */
SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_CLASS, PVRSRVEnumerateDCBW);
-
+ /* display class API */
SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_DISPCLASS_DEVICE, PVRSRVOpenDCDeviceBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE, PVRSRVCloseDCDeviceBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_FORMATS, PVRSRVEnumDCFormatsBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_ENUM_DISPCLASS_DIMS, PVRSRVEnumDCDimsBW);
+#if defined(SUPPORT_PVRSRV_GET_DC_SYSTEM_BUFFER)
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, PVRSRVGetDCSystemBufferBW);
+#else
+ SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_SYSBUFFER, DummyBW);
+#endif
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_INFO, PVRSRVGetDCInfoBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_CREATE_DISPCLASS_SWAPCHAIN, PVRSRVCreateDCSwapChainBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_DESTROY_DISPCLASS_SWAPCHAIN, PVRSRVDestroyDCSwapChainBW);
@@ -4728,28 +5295,29 @@ CommonBridgeInit(IMG_VOID)
SetDispatchTableEntry(PVRSRV_BRIDGE_SET_DISPCLASS_SRCCOLOURKEY, PVRSRVSetDCSrcColourKeyBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_DISPCLASS_BUFFERS, PVRSRVGetDCBuffersBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER, PVRSRVSwapToDCBufferBW);
+ SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_BUFFER2, PVRSRVSwapToDCBuffer2BW);
SetDispatchTableEntry(PVRSRV_BRIDGE_SWAP_DISPCLASS_TO_SYSTEM, PVRSRVSwapToDCSystemBW);
-
+ /* buffer class API */
SetDispatchTableEntry(PVRSRV_BRIDGE_OPEN_BUFFERCLASS_DEVICE, PVRSRVOpenBCDeviceBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_CLOSE_BUFFERCLASS_DEVICE, PVRSRVCloseBCDeviceBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_INFO, PVRSRVGetBCInfoBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_GET_BUFFERCLASS_BUFFER, PVRSRVGetBCBufferBW);
-
+ /* Wrap/Unwrap external memory */
SetDispatchTableEntry(PVRSRV_BRIDGE_WRAP_EXT_MEMORY, PVRSRVWrapExtMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_UNWRAP_EXT_MEMORY, PVRSRVUnwrapExtMemoryBW);
-
+ /* Shared memory */
SetDispatchTableEntry(PVRSRV_BRIDGE_ALLOC_SHARED_SYS_MEM, PVRSRVAllocSharedSysMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_FREE_SHARED_SYS_MEM, PVRSRVFreeSharedSysMemoryBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_MAP_MEMINFO_MEM, PVRSRVMapMemInfoMemBW);
-
+ /* Intialisation Service support */
SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_CONNECT, &PVRSRVInitSrvConnectBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_INITSRV_DISCONNECT, &PVRSRVInitSrvDisconnectBW);
-
+ /* Event Object */
SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_WAIT, &PVRSRVEventObjectWaitBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_OPEN, &PVRSRVEventObjectOpenBW);
SetDispatchTableEntry(PVRSRV_BRIDGE_EVENT_OBJECT_CLOSE, &PVRSRVEventObjectCloseBW);
@@ -4775,9 +5343,11 @@ CommonBridgeInit(IMG_VOID)
SetMSVDXDispatchTableEntry();
#endif
-
-
-
+ /* A safety net to help ensure there won't be any un-initialised dispatch
+ * table entries... */
+ /* Note: This is specifically done _after_ setting all the dispatch entries
+ * so that SetDispatchTableEntry can detect mistakes where entries
+ * overlap */
for(i=0;i<BRIDGE_DISPATCH_TABLE_ENTRY_COUNT;i++)
{
if(!g_BridgeDispatchTable[i].pfFunction)
@@ -4797,9 +5367,8 @@ CommonBridgeInit(IMG_VOID)
}
IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
- PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
+ PVRSRV_BRIDGE_PACKAGE * psBridgePackageKM)
{
-
IMG_VOID * psBridgeIn;
IMG_VOID * psBridgeOut;
BridgeWrapperFunction pfBridgeHandler;
@@ -4838,7 +5407,7 @@ IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
}
else
{
-
+ /* Only certain operations are allowed */
switch(ui32BridgeID)
{
case PVRSRV_GET_BRIDGE_ID(PVRSRV_BRIDGE_CONNECT_SERVICES):
@@ -4855,20 +5424,18 @@ IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
}
}
-
-
#if defined(__linux__)
{
-
+ /* This should be moved into the linux specific code */
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
-
+ /* We have already set up some static buffers to store our ioctl data... */
psBridgeIn = ((ENV_DATA *)psSysData->pvEnvSpecificData)->pvBridgeData;
psBridgeOut = (IMG_PVOID)((IMG_PBYTE)psBridgeIn + PVRSRV_MAX_BRIDGE_IN_SIZE);
-
+ /* check we are not using a bigger bridge than allocated */
if((psBridgePackageKM->ui32InBufferSize > PVRSRV_MAX_BRIDGE_IN_SIZE) ||
(psBridgePackageKM->ui32OutBufferSize > PVRSRV_MAX_BRIDGE_OUT_SIZE))
{
@@ -4909,26 +5476,17 @@ IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
}
pfBridgeHandler =
(BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
- if(ui32BridgeID >= (BRIDGE_DISPATCH_TABLE_ENTRY_COUNT))
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: ui32BridgeID = %d is out if range!",
- __FUNCTION__, ui32BridgeID));
- goto return_fault;
- }
- pfBridgeHandler =
- (BridgeWrapperFunction)g_BridgeDispatchTable[ui32BridgeID].pfFunction;
- err = pfBridgeHandler(ui32BridgeID,
- psBridgeIn,
- psBridgeOut,
- psPerProc);
- if(err < 0)
- {
- goto return_fault;
- }
-
+ err = pfBridgeHandler(ui32BridgeID,
+ psBridgeIn,
+ psBridgeOut,
+ psPerProc);
+ if(err < 0)
+ {
+ goto return_fault;
+ }
#if defined(__linux__)
-
+ /* This should be moved into the linux specific code */
if(CopyToUserWrapper(psPerProc,
ui32BridgeID,
psBridgePackageKM->pvParamOut,
@@ -4947,3 +5505,6 @@ return_fault:
return err;
}
+/******************************************************************************
+ End of file (bridged_pvr_bridge.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/bridged/bridged_pvr_bridge.h b/sgx/services4/srvkm/bridged/bridged_pvr_bridge.h
index 6b0dd88..131cecd 100644
--- a/sgx/services4/srvkm/bridged/bridged_pvr_bridge.h
+++ b/sgx/services4/srvkm/bridged/bridged_pvr_bridge.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __BRIDGED_PVR_BRIDGE_H__
#define __BRIDGED_PVR_BRIDGE_H__
@@ -138,11 +155,11 @@ ReleaseHandleBatch(PVRSRV_PER_PROCESS_DATA *psPerProc)
PVRSRVReleaseHandleBatch(psPerProc->psHandleBase);
}
}
-#else
+#else /* defined(PVR_SECURE_HANDLES) */
#define NEW_HANDLE_BATCH_OR_ERROR(error, psPerProc, ui32BatchSize)
#define COMMIT_HANDLE_BATCH_OR_ERROR(error, psPerProc)
#define ReleaseHandleBatch(psPerProc)
-#endif
+#endif /* defined(PVR_SECURE_HANDLES) */
IMG_INT
DummyBW(IMG_UINT32 ui32BridgeID,
@@ -157,13 +174,16 @@ typedef IMG_INT (*BridgeWrapperFunction)(IMG_UINT32 ui32BridgeID,
typedef struct _PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY
{
- BridgeWrapperFunction pfFunction;
+ BridgeWrapperFunction pfFunction; /*!< The wrapper function that validates the ioctl
+ arguments before calling into srvkm proper */
#if defined(DEBUG_BRIDGE_KM)
- const IMG_CHAR *pszIOCName;
- const IMG_CHAR *pszFunctionName;
- IMG_UINT32 ui32CallCount;
- IMG_UINT32 ui32CopyFromUserTotalBytes;
- IMG_UINT32 ui32CopyToUserTotalBytes;
+ const IMG_CHAR *pszIOCName; /*!< Name of the ioctl: e.g. "PVRSRV_BRIDGE_CONNECT_SERVICES" */
+ const IMG_CHAR *pszFunctionName; /*!< Name of the wrapper function: e.g. "PVRSRVConnectBW" */
+ IMG_UINT32 ui32CallCount; /*!< The total number of times the ioctl has been called */
+ IMG_UINT32 ui32CopyFromUserTotalBytes; /*!< The total number of bytes copied from
+ userspace within this ioctl */
+ IMG_UINT32 ui32CopyToUserTotalBytes; /*!< The total number of bytes copied from
+ userspace within this ioctl */
#endif
}PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY;
@@ -194,7 +214,7 @@ _SetDispatchTableEntry(IMG_UINT32 ui32Index,
const IMG_CHAR *pszFunctionName);
-
+/* PRQA S 0884,3410 2*/ /* macro relies on the lack of brackets */
#define SetDispatchTableEntry(ui32Index, pfFunction) \
_SetDispatchTableEntry(PVRSRV_GET_BRIDGE_ID(ui32Index), #ui32Index, (BridgeWrapperFunction)pfFunction, #pfFunction)
@@ -215,6 +235,9 @@ typedef struct _PVRSRV_BRIDGE_GLOBAL_STATS
IMG_UINT32 ui32TotalCopyToUserBytes;
}PVRSRV_BRIDGE_GLOBAL_STATS;
+/* OS specific code way want to report the stats held here and within the
+ * BRIDGE_DISPATCH_TABLE_ENTRYs (E.g. on Linux we report these via a
+ * proc entry /proc/pvr/bridge_stats. Ref printLinuxBridgeStats()) */
extern PVRSRV_BRIDGE_GLOBAL_STATS g_BridgeGlobalStats;
#endif
@@ -228,5 +251,8 @@ IMG_INT BridgedDispatchKM(PVRSRV_PER_PROCESS_DATA * psPerProc,
}
#endif
-#endif
+#endif /* __BRIDGED_PVR_BRIDGE_H__ */
+/******************************************************************************
+ End of file (bridged_pvr_bridge.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/bridged/bridged_support.c b/sgx/services4/srvkm/bridged/bridged_support.c
index dad0800..bd17e91 100644
--- a/sgx/services4/srvkm/bridged/bridged_support.c
+++ b/sgx/services4/srvkm/bridged/bridged_support.c
@@ -1,34 +1,57 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Support Functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description User/kernel mode bridge support. The functions in here
+ may be used beyond the bridge code proper (e.g. Linux
+ mmap interface).
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "img_defs.h"
#include "servicesint.h"
#include "bridged_support.h"
+/*
+ * Derive the internal OS specific memory handle from a secure
+ * handle.
+ */
PVRSRV_ERROR
#if defined (SUPPORT_SID_INTERFACE)
PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHandle, IMG_SID hMHandle)
@@ -40,7 +63,10 @@ PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHan
PVRSRV_HANDLE_TYPE eHandleType;
PVRSRV_ERROR eError;
-
+ /*
+ * We don't know the type of the handle at this point, so we use
+ * PVRSRVLookupHandleAnyType to look it up.
+ */
eError = PVRSRVLookupHandleAnyType(psHandleBase, &hMHandleInt,
&eHandleType,
hMHandle);
@@ -87,3 +113,6 @@ PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psHandleBase, IMG_HANDLE *phOSMemHan
return PVRSRV_OK;
}
+/******************************************************************************
+ End of file (bridged_support.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/bridged/bridged_support.h b/sgx/services4/srvkm/bridged/bridged_support.h
index d027290..9cd80f5 100644
--- a/sgx/services4/srvkm/bridged/bridged_support.h
+++ b/sgx/services4/srvkm/bridged/bridged_support.h
@@ -1,28 +1,47 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Support
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description User/kernel mode bridge support. The functions in here
+ may be used beyond the bridge code proper (e.g. Linux
+ mmap interface).
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __BRIDGED_SUPPORT_H__
#define __BRIDGED_SUPPORT_H__
@@ -33,6 +52,10 @@
extern "C" {
#endif
+/*
+ * Derive the internal OS specific memory handle from a secure
+ * handle.
+ */
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phOSMemHandle, IMG_SID hMHandle);
#else
@@ -43,5 +66,8 @@ PVRSRV_ERROR PVRSRVLookupOSMemHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phO
}
#endif
-#endif
+#endif /* __BRIDGED_SUPPORT_H__ */
+/******************************************************************************
+ End of file (bridged_support.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c b/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
index c7472f0..625705b 100644
--- a/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
+++ b/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.c
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Common Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
@@ -103,7 +121,9 @@ SGXReleaseClientInfoBW(IMG_UINT32 ui32BridgeID,
PVR_ASSERT(psDevInfo->ui32ClientRefCount > 0);
-
+ /*
+ * psDevInfo->ui32ClientRefCount can be zero if an error occurred before SGXGetClientInfo is called
+ */
if (psDevInfo->ui32ClientRefCount > 0)
{
psDevInfo->ui32ClientRefCount--;
@@ -146,7 +166,10 @@ SGXGetInternalDevInfoBW(IMG_UINT32 ui32BridgeID,
&psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo);
#endif
-
+ /*
+ * Handle is not allocated in batch mode, as there is no resource
+ * allocation to undo if the handle allocation fails.
+ */
psSGXGetInternalDevInfoOUT->eError =
PVRSRVAllocHandle(psPerProc->psHandleBase,
&psSGXGetInternalDevInfoOUT->sSGXInternalDevInfo.hHostCtlKernelMemInfoHandle,
@@ -259,7 +282,7 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
}
#if defined(FIX_HW_BRN_31620)
-
+ /* We need to lookup the mem context and pass it through */
psRetOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&psDoKickIN->sCCBKick.hDevMemContext,
@@ -296,7 +319,7 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST sync details */
if (psDoKickIN->sCCBKick.ui32NumTASrcSyncs > SGX_MAX_TA_SRC_SYNCS)
{
psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
@@ -377,9 +400,9 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
return 0;
}
}
-#else
-
- if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS)
+#else/* #if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) */
+ /* texture dependency details */
+ if (psDoKickIN->sCCBKick.ui32NumSrcSyncs > SGX_MAX_SRC_SYNCS_TA)
{
psRetOUT->eError = PVRSRV_ERROR_INVALID_PARAMS;
return 0;
@@ -405,7 +428,7 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
return 0;
}
}
-#endif
+#endif/* #if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS) */
if (psDoKickIN->sCCBKick.ui32NumTAStatusVals > SGX_MAX_TA_STATUS_VALS)
{
@@ -519,7 +542,7 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
goto PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT;
}
-
+ /* Set sCCBKick.pahDstSyncHandles to point to the local memory */
psDoKickIN->sCCBKick.pahDstSyncHandles = phKernelSyncInfoHandles;
#endif
@@ -578,7 +601,7 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
#if defined(NO_HARDWARE)
sCCBKickKM.ui32WriteOpsPendingVal = psDoKickIN->sCCBKick.ui32WriteOpsPendingVal;
#endif
-#endif
+#endif /* #if defined (SUPPORT_SID_INTERFACE) */
psRetOUT->eError =
SGXDoKickKM(hDevCookieInt,
#if defined (SUPPORT_SID_INTERFACE)
@@ -589,13 +612,14 @@ SGXDoKickBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_SGX_DOKICK_RETURN_RESULT:
+//#if (!defined(_UITRON_) && !defined(UNDER_VISTA)) || defined (SUPPORT_SID_INTERFACE)
if(phKernelSyncInfoHandles)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
ui32NumDstSyncs * sizeof(IMG_HANDLE),
(IMG_VOID *)phKernelSyncInfoHandles,
0);
-
+ /*not nulling pointer, out of scope*/
}
return ret;
}
@@ -648,7 +672,7 @@ SGXSubmitTransferBW(IMG_UINT32 ui32BridgeID,
psKick = &psSubmitTransferIN->sKick;
#if defined(FIX_HW_BRN_31620)
-
+ /* We need to lookup the mem context and pass it through */
psRetOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&psKick->hDevMemContext,
@@ -887,7 +911,7 @@ SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
psKick = &psSubmit2DIN->sKick;
#if defined(FIX_HW_BRN_31620)
-
+ /* We need to lookup the mem context and pass it through */
psRetOUT->eError =
PVRSRVLookupHandle(psPerProc->psHandleBase,
&psKick->hDevMemContext,
@@ -1039,7 +1063,7 @@ SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
sKickKM.hDstSyncInfo = IMG_NULL;
}
-
+ /* copy common members across */
sKickKM.ui32SharedCmdCCBOffset = psKick->ui32SharedCmdCCBOffset;
sKickKM.ui32NumSrcSync = psKick->ui32NumSrcSync;
sKickKM.ui32PDumpFlags = psKick->ui32PDumpFlags;
@@ -1058,8 +1082,8 @@ SGXSubmit2DBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-#endif
-#endif
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* #if defined(TRANSFER_QUEUE) */
static IMG_INT
@@ -1088,7 +1112,7 @@ SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
}
#if defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
-
+ /* Lookup handle for dev mem context */
if (psSGXGetMiscInfoIN->psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMREAD)
{
psRetOUT->eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
@@ -1102,7 +1126,7 @@ SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
}
}
#endif
-
+ /* device node is required for scheduling a CCB command */
psDeviceNode = hDevCookieInt;
PVR_ASSERT(psDeviceNode != IMG_NULL);
if (psDeviceNode == IMG_NULL)
@@ -1112,7 +1136,7 @@ SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
psDevInfo = psDeviceNode->pvDevice;
-
+ /* Copy psMiscInfo to kernel space */
psRetOUT->eError = CopyFromUserWrapper(psPerProc,
ui32BridgeID,
&sMiscInfo,
@@ -1132,7 +1156,7 @@ SGXGetMiscInfoBW(IMG_UINT32 ui32BridgeID,
}
}
-
+ /* Copy back misc info to user address space */
psRetOUT->eError = CopyToUserWrapper(psPerProc,
ui32BridgeID,
psSGXGetMiscInfoIN->psMiscInfo,
@@ -1197,7 +1221,7 @@ SGXReadHWPerfCBBW(IMG_UINT32 ui32BridgeID,
ui32AllocatedSize,
psAllocated,
hAllocatedHandle);
-
+ /*not nulling pointer, out of scope*/
return 0;
}
@@ -1226,7 +1250,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_DEVINITPART2);
-
+ /* Report the kernel-side build options to UM */
psSGXDevInitPart2OUT->ui32KMBuildOptions = SGX_BUILD_OPTIONS;
if(!psPerProc->bInitProcess)
@@ -1245,7 +1269,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* Check all the meminfo handles */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDummy,
psSGXDevInitPart2IN->sInitInfo.hKernelCCBMemInfo,
@@ -1374,7 +1398,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
#endif
-#if defined(FIX_HW_BRN_31542)
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDummy,
psSGXDevInitPart2IN->sInitInfo.hKernelClearClipWAVDMStreamMemInfo,
@@ -1442,7 +1466,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
}
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDummy,
psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
@@ -1518,7 +1542,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
+ /* Lookup and release the device memory handles */
eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
#if defined (SUPPORT_SID_INTERFACE)
&asInitInfoKM.hKernelCCBMemInfo,
@@ -1701,7 +1725,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
#endif
-#if defined(FIX_HW_BRN_31542)
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
#if defined (SUPPORT_SID_INTERFACE)
&asInitInfoKM.hKernelClearClipWAVDMStreamMemInfo,
@@ -1799,7 +1823,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
bReleaseFailed = IMG_TRUE;
}
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
eError = PVRSRVLookupAndReleaseHandle(psPerProc->psHandleBase,
&psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo,
@@ -1878,12 +1902,15 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
{
PVR_DPF((PVR_DBG_ERROR, "DevInitSGXPart2BW: A handle release failed"));
psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
-
+ /*
+ * Given that we checked the handles before release, a release
+ * failure is unexpected.
+ */
PVR_DBG_BREAK;
return 0;
}
-
+ /* Dissociate device memory from caller */
#if defined (SUPPORT_SID_INTERFACE)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelCCBMemInfo);
#else
@@ -1946,7 +1973,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
}
#endif
-
+ /* Dissociate SGX MiscInfo buffer from user space */
#if defined (SUPPORT_SID_INTERFACE)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelSGXMiscMemInfo);
#else
@@ -2029,7 +2056,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
#endif
#endif
-#if defined(FIX_HW_BRN_31542)
+#if defined(FIX_HW_BRN_31542) || defined(FIX_HW_BRN_36513)
#if defined (SUPPORT_SID_INTERFACE)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, asInitInfoKM.hKernelClearClipWAVDMStreamMemInfo);
if (eError != PVRSRV_OK)
@@ -2112,7 +2139,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
#endif
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
eError = PVRSRVDissociateDeviceMemKM(hDevCookieInt, psSGXDevInitPart2IN->sInitInfo.hKernelVDMSnapShotBufferMemInfo);
bDissociateFailed |= (IMG_BOOL)(eError != PVRSRV_OK);
@@ -2156,7 +2183,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
}
}
-
+ /* If any dissociations failed, free all the device memory passed in */
if(bDissociateFailed)
{
#if defined (SUPPORT_SID_INTERFACE)
@@ -2200,7 +2227,7 @@ SGXDevInitPart2BW(IMG_UINT32 ui32BridgeID,
psSGXDevInitPart2OUT->eError = PVRSRV_ERROR_INIT2_PHASE_FAILED;
-
+ /* A dissociation failure is unexpected */
PVR_DBG_BREAK;
return 0;
}
@@ -2244,6 +2271,7 @@ SGXRegisterHWRenderContextBW(IMG_UINT32 ui32BridgeID,
PVRSRV_PER_PROCESS_DATA *psPerProc)
{
IMG_HANDLE hDevCookieInt;
+// PVRSRV_SGXDEV_INFO *psDevInfo;
IMG_HANDLE hHWRenderContextInt;
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_REGISTER_HW_RENDER_CONTEXT);
@@ -2498,7 +2526,7 @@ SGXUnregisterHW2DContextBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-#endif
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
static IMG_INT
SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
@@ -2507,6 +2535,8 @@ SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
PVRSRV_PER_PROCESS_DATA *psPerProc)
{
IMG_HANDLE hDevCookieInt;
+// PVRSRV_SGXDEV_INFO *psDevInfo;
+
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_FLUSH_HW_RENDER_TARGET);
psRetOUT->eError =
@@ -2519,6 +2549,8 @@ SGXFlushHWRenderTargetBW(IMG_UINT32 ui32BridgeID,
return 0;
}
+// psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookieInt)->pvDevice;
+
psRetOUT->eError = SGXFlushHWRenderTargetKM(hDevCookieInt, psSGXFlushHWRenderTargetIN->sHWRTDataSetDevVAddr, IMG_FALSE);
return 0;
@@ -2621,7 +2653,8 @@ SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
if(hSharedPBDesc == IMG_NULL)
{
psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle = 0;
-
+ /* It's not an error if we don't find a buffer,
+ * we just return NULL */
goto PVRSRV_BRIDGE_SGX_FINDSHAREDPBDESC_EXIT;
}
@@ -2631,7 +2664,12 @@ SGXFindSharedPBDescBW(IMG_UINT32 ui32BridgeID,
PVRSRV_HANDLE_TYPE_SHARED_PB_DESC,
PVRSRV_HANDLE_ALLOC_FLAG_NONE);
-
+ /*
+ * We allocate handles of type PVRSRV_HANDLE_TYPE_MEM_INFO_REF here,
+ * as the process doesn't own the underlying memory, and so should
+ * only be allowed a restricted set of operations on it, such as
+ * mapping it into its address space.
+ */
PVRSRVAllocSubHandleNR(psPerProc->psHandleBase,
&psSGXFindSharedPBDescOUT->hSharedPBDescKernelMemInfoHandle,
psSharedPBDescKernelMemInfo,
@@ -2868,26 +2906,30 @@ SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
}
}
-
-
+ /*
+ * Release all the handles we've just looked up, as none
+ * of the associated resources will be valid for access via
+ * those handles once we return from SGXAddSharedPBDesc.
+ */
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hSharedPBDescKernelMemInfo,
PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
PVR_ASSERT(eError == PVRSRV_OK);
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hHWPBDescKernelMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO);
PVR_ASSERT(eError == PVRSRV_OK);
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hBlockKernelMemInfo,
PVRSRV_HANDLE_TYPE_SHARED_SYS_MEM_INFO);
PVR_ASSERT(eError == PVRSRV_OK);
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
psSGXAddSharedPBDescIN->hHWBlockKernelMemInfo,
PVRSRV_HANDLE_TYPE_MEM_INFO);
@@ -2895,7 +2937,7 @@ SGXAddSharedPBDescBW(IMG_UINT32 ui32BridgeID,
for(i=0; i<ui32KernelMemInfoHandlesCount; i++)
{
-
+ /* PRQA S 3198 2 */ /* override redundant warning as PVR_ASSERT is ignored by QAC */
eError = PVRSRVReleaseHandle(psPerProc->psHandleBase,
phKernelMemInfoHandles[i],
PVRSRV_HANDLE_TYPE_MEM_INFO);
@@ -3007,7 +3049,7 @@ SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
if ((asHeapInfo[i].ui32HeapID != (IMG_UINT32)SGX_UNDEFINED_HEAP_ID) &&
(asHeapInfo[i].hDevMemHeap != IMG_NULL))
{
-
+ /* Allocate heap handle */
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&psHeapInfo->hDevMemHeap,
asHeapInfo[i].hDevMemHeap,
@@ -3031,7 +3073,7 @@ SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
if (psHeapInfo->hDevMemHeap != IMG_NULL)
{
-
+ /* Allocate heap handle */
PVRSRVAllocHandleNR(psPerProc->psHandleBase,
&hDevMemHeapExt,
psHeapInfo->hDevMemHeap,
@@ -3049,6 +3091,13 @@ SGXGetInfoForSrvinitBW(IMG_UINT32 ui32BridgeID,
}
#if defined(PDUMP)
+// PRQA S 5120++
+/*****************************************************************************
+ FUNCTION : DumpBufferArray
+ PURPOSE : PDUMP information in stored buffer array
+ PARAMETERS :
+ RETURNS :
+*****************************************************************************/
static IMG_VOID
DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
@@ -3116,7 +3165,9 @@ DumpBufferArray(PVRSRV_PER_PROCESS_DATA *psPerProc,
}
else
{
-
+ /*
+ Range of data wraps the end of the buffer so it needs to be dumped in two sections
+ */
if (bDumpPolls)
{
@@ -3181,6 +3232,11 @@ SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
SGX_KICKTA_DUMP_BUFFER *psUMPtr;
SGX_KICKTA_DUMP_BUFFER_KM *psKickTADumpBufferKM, *psKMPtr;
#else
+#if defined(__QNXNTO__)
+ const IMG_UINT32 NAME_BUFFER_SIZE = 30;
+ IMG_PCHAR pszNameBuffer, pszName;
+ IMG_UINT32 ui32NameBufferArraySize, ui32NameLength;
+#endif
SGX_KICKTA_DUMP_BUFFER *psKickTADumpBuffer;
#endif
IMG_UINT32 ui32BufferArrayLength =
@@ -3189,12 +3245,6 @@ SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
ui32BufferArrayLength * sizeof(SGX_KICKTA_DUMP_BUFFER);
PVRSRV_ERROR eError = PVRSRV_ERROR_TOO_FEW_BUFFERS;
-#if defined (__QNXNTO__)
- const IMG_UINT32 MAX_BUFFER_NAME_SIZE = 30;
- IMG_PCHAR pszNamesBuffer, pszName;
- IMG_UINT32 ui32NameBufferArraySize;
-#endif
-
PVR_UNREFERENCED_PARAMETER(psBridgeOut);
PVRSRV_BRIDGE_ASSERT_CMD(ui32BridgeID, PVRSRV_BRIDGE_SGX_PDUMP_BUFFER_ARRAY);
@@ -3222,39 +3272,49 @@ SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
ui32BufferArraySize) != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
-
+ /*not nulling pointer, out of scope*/
return -EFAULT;
}
-#endif
#if defined (__QNXNTO__)
- ui32NameBufferArraySize = ui32BufferArrayLength * MAX_BUFFER_NAME_SIZE;
+ ui32NameBufferArraySize = ui32BufferArrayLength * NAME_BUFFER_SIZE;
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize,
- (IMG_PVOID *)&pszNamesBuffer, 0,
+ (IMG_PVOID *)&pszNameBuffer, 0,
"Kick Tile Accelerator Dump Buffer names") != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
return -ENOMEM;
}
- pszName = pszNamesBuffer;
+ pszName = pszNameBuffer;
+
for (i=0; i<ui32BufferArrayLength; i++)
{
- if (CopyFromUserWrapper(psPerProc, ui32BridgeID,
- pszName, psKickTADumpBuffer[i].pszName,
- MAX_BUFFER_NAME_SIZE) != PVRSRV_OK)
+ if (psKickTADumpBuffer[i].pszName)
{
- PVR_DPF((PVR_DBG_WARNING, "Failed to read pdump buffer name"));
- psKickTADumpBuffer[i].pszName = 0;
+ ui32NameLength = psKickTADumpBuffer[i].ui32NameLength;
+ if (ui32NameLength >= NAME_BUFFER_SIZE)
+ {
+ ui32NameLength = NAME_BUFFER_SIZE - 1;
+ }
+
+ if (ui32NameLength &&
+ (CopyFromUserWrapper(psPerProc, ui32BridgeID, pszName,
+ psKickTADumpBuffer[i].pszName, ui32NameLength + 1) == PVRSRV_OK))
+ {
+ pszName[NAME_BUFFER_SIZE - 1] = 0;
+ psKickTADumpBuffer[i].pszName = pszName;
+ pszName += NAME_BUFFER_SIZE;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_WARNING, "Failed to read PDUMP buffer name"));
+ psKickTADumpBuffer[i].pszName = 0;
+ }
}
- else
- {
- pszName[MAX_BUFFER_NAME_SIZE-1] = 0;
- psKickTADumpBuffer[i].pszName = pszName;
- }
- pszName += MAX_BUFFER_NAME_SIZE;
}
#endif
+#endif
for(i = 0; i < ui32BufferArrayLength; i++)
{
@@ -3339,12 +3399,11 @@ SGXPDumpBufferArrayBW(IMG_UINT32 ui32BridgeID,
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBufferKM, 0);
#else
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32BufferArraySize, psKickTADumpBuffer, 0);
-#endif
-
-
#if defined (__QNXNTO__)
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize, pszNamesBuffer, 0);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, ui32NameBufferArraySize, pszNameBuffer, 0);
#endif
+#endif
+ /*not nulling pointer, out of scope*/
return 0;
}
@@ -3389,7 +3448,7 @@ SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
#if defined(SGX_FEATURE_MP) && defined(FIX_HW_BRN_27270)
-
+ /* Enable all cores available */
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
#if defined(PDUMP)
@@ -3433,8 +3492,8 @@ SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
- PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ /* look up the MMU context ID */
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID((IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext);
PDumpSignatureBuffer(&psDeviceNode->sDevId,
@@ -3442,13 +3501,13 @@ SGXPDump3DSignatureRegistersBW(IMG_UINT32 ui32BridgeID,
psDevInfo->psKernelTASigBufferMemInfo->sDevVAddr,
(IMG_UINT32)psDevInfo->psKernelTASigBufferMemInfo->uAllocSize,
ui32MMUContextID,
- 0 );
+ 0 /*ui32PDumpFlags*/);
PDumpSignatureBuffer(&psDeviceNode->sDevId,
"out.3dsig", "3D", 0,
psDevInfo->psKernel3DSigBufferMemInfo->sDevVAddr,
(IMG_UINT32)psDevInfo->psKernel3DSigBufferMemInfo->uAllocSize,
ui32MMUContextID,
- 0 );
+ 0 /*ui32PDumpFlags*/);
ExitNoError:
psRetOUT->eError = PVRSRV_OK;
@@ -3578,7 +3637,7 @@ SGXPDumpTASignatureRegistersBW(IMG_UINT32 ui32BridgeID,
psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
-
+ /* Enable all cores available */
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE, (SGX_FEATURE_MP_CORE_COUNT - 1) << EUR_CR_MASTER_CORE_ENABLE_SHIFT);
#if defined(PDUMP)
@@ -3636,6 +3695,9 @@ Exit:
return ret;
}
+//PRQA S 5120--
+
+
static IMG_INT
SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
PVRSRV_BRIDGE_IN_PDUMP_HWPERFCB *psPDumpHWPerfCBIN,
@@ -3672,8 +3734,8 @@ SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
- PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ /* look up the MMU context ID */
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
PDumpHWPerfCBKM(&psDeviceNode->sDevId,
@@ -3691,14 +3753,14 @@ SGXPDumpHWPerfCBBW(IMG_UINT32 ui32BridgeID,
PVR_UNREFERENCED_PARAMETER(psRetOUT);
PVR_UNREFERENCED_PARAMETER(psPerProc);
return 0;
-#endif
+#endif /* defined(LINUX) || defined(UNDER_XP) */
#else
PVR_UNREFERENCED_PARAMETER(ui32BridgeID);
PVR_UNREFERENCED_PARAMETER(psPDumpHWPerfCBIN);
PVR_UNREFERENCED_PARAMETER(psRetOUT);
PVR_UNREFERENCED_PARAMETER(psPerProc);
return -EFAULT;
-#endif
+#endif /* defined(SUPPORT_SGX_HWPERF) */
}
@@ -3734,8 +3796,8 @@ SGXPDumpSaveMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-
- PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL)
+ /* look up the MMU context ID */
+ PVR_ASSERT(psDeviceNode->pfnMMUGetContextID != IMG_NULL);
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID(hDevMemContextInt);
PDumpSaveMemKM(&psDeviceNode->sDevId,
@@ -3748,10 +3810,10 @@ SGXPDumpSaveMemBW(IMG_UINT32 ui32BridgeID,
return 0;
}
-#endif
+#endif /* PDUMP */
-
+/* PRQA S 0313,3635 END_SET_SGX */ /* function macro required this format */
IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
{
@@ -3800,6 +3862,6 @@ IMG_VOID SetSGXDispatchTableEntry(IMG_VOID)
SetDispatchTableEntry(PVRSRV_BRIDGE_SGX_PDUMP_SAVEMEM, SGXPDumpSaveMemBW);
#endif
}
-
+/* PRQA L:END_SET_SGX */ /* end of setup overrides */
-#endif
+#endif /* SUPPORT_SGX */
diff --git a/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h b/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
index 204450c..02ea7c4 100644
--- a/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
+++ b/sgx/services4/srvkm/bridged/sgx/bridged_sgx_bridge.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the PVR Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __BRIDGED_SGX_BRIDGE_H__
#define __BRIDGED_SGX_BRIDGE_H__
@@ -38,5 +55,8 @@ IMG_VOID SetSGXDispatchTableEntry(IMG_VOID);
}
#endif
-#endif
+#endif /* __BRIDGED_SGX_BRIDGE_H__ */
+/******************************************************************************
+ End of file (bridged_sgx_bridge.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/buffer_manager.c b/sgx/services4/srvkm/common/buffer_manager.c
index e92fa6c..45d63b4 100644
--- a/sgx/services4/srvkm/common/buffer_manager.c
+++ b/sgx/services4/srvkm/common/buffer_manager.c
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Buffer management functions for Linux
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manages buffers mapped into two memory spaces - cpu and device,
+ either of which can be virtual or physical.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
@@ -38,8 +56,9 @@ static IMG_VOID
BM_FreeMemory (IMG_VOID *pH, IMG_UINTPTR_T base, BM_MAPPING *psMapping);
static IMG_BOOL
BM_ImportMemory(IMG_VOID *pH, IMG_SIZE_T uSize,
- IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
- IMG_UINT32 uFlags, IMG_UINTPTR_T *pBase);
+ IMG_SIZE_T *pActualSize, BM_MAPPING **ppsMapping,
+ IMG_UINT32 uFlags, IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength, IMG_UINTPTR_T *pBase);
static IMG_BOOL
DevMemoryAlloc (BM_CONTEXT *pBMContext,
@@ -51,14 +70,53 @@ DevMemoryAlloc (BM_CONTEXT *pBMContext,
static IMG_VOID
DevMemoryFree (BM_MAPPING *pMapping);
+/*!
+******************************************************************************
+
+ @Function AllocMemory
+
+ @Description Allocate a buffer mapped into both cpu and device virtual
+ address spaces. This is now quite simple:
+
+ 1. Choose whence to get the memory;
+ 2. Obtain memory from that source;
+ 3. Work out the actual buffer addresses in other spaces.
+
+ In choosing whence to get the memory we work like this:
+
+ 1. If an import arena exists, use unless BP_CONTIGUOUS is set;
+ 2. Use a contiguous pool.
+
+ @Input pBMContext - BM context
+ @Input psBMHeap - BM heap
+ @Input psDevVAddr - device virtual address (optional)
+ @Input uSize - requested buffer size in bytes.
+ @Input uFlags - property flags for the buffer.
+ @Input uDevVAddrAlignment - required device virtual address
+ alignment, or 0.
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+
+ @Output pBuf - receives a pointer to a descriptor of the allocated
+ buffer.
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed.
+
+ *****************************************************************************/
static IMG_BOOL
-AllocMemory (BM_CONTEXT *pBMContext,
- BM_HEAP *psBMHeap,
- IMG_DEV_VIRTADDR *psDevVAddr,
- IMG_SIZE_T uSize,
- IMG_UINT32 uFlags,
- IMG_UINT32 uDevVAddrAlignment,
- BM_BUF *pBuf)
+AllocMemory (BM_CONTEXT *pBMContext,
+ BM_HEAP *psBMHeap,
+ IMG_DEV_VIRTADDR *psDevVAddr,
+ IMG_SIZE_T uSize,
+ IMG_UINT32 uFlags,
+ IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ BM_BUF *pBuf)
{
BM_MAPPING *pMapping;
IMG_UINTPTR_T uOffset;
@@ -68,16 +126,18 @@ AllocMemory (BM_CONTEXT *pBMContext,
"AllocMemory (uSize=0x%x, uFlags=0x%x, align=0x%x)",
uSize, uFlags, uDevVAddrAlignment));
-
-
-
+ /*
+ what to do depends on combination of DevVaddr generation
+ and backing RAM requirement
+ */
if (uFlags & PVRSRV_HAP_GPU_PAGEABLE)
{
/* in case of a pageable buffer, we must bypass RA which could
* combine/split individual mappings between buffers:
*/
if (!BM_ImportMemory(psBMHeap, uSize, IMG_NULL, &pMapping,
- uFlags, (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+ uFlags, NULL, 0,
+ (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
{
PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: failed"));
return IMG_FALSE;
@@ -88,19 +148,19 @@ AllocMemory (BM_CONTEXT *pBMContext,
{
if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
{
-
+ /* user supplied DevVAddr, RAM backing */
PVR_DPF ((PVR_DBG_ERROR, "AllocMemory: combination of DevVAddr management and RAM backing mode unsupported"));
return IMG_FALSE;
}
-
+ /* BM supplied DevVAddr, RAM Backing */
-
+ /* check heap attributes */
if(psBMHeap->ui32Attribs
& (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
{
-
+ /* specify arena (VM+RAM)*/
pArena = psBMHeap->pImportArena;
PVR_ASSERT(psBMHeap->sDevArena.psDeviceMemoryHeapInfo->ui32Attribs & PVRSRV_MEM_RAM_BACKED_ALLOCATION);
}
@@ -110,18 +170,76 @@ AllocMemory (BM_CONTEXT *pBMContext,
return IMG_FALSE;
}
+ /* Now allocate from the arena we chose above. */
+ if (uFlags & PVRSRV_MEM_SPARSE)
+ {
+ IMG_BOOL bSuccess;
+ IMG_SIZE_T puiActualSize;
+
+ /* Allocate physcial memory */
+ bSuccess = BM_ImportMemory(psBMHeap,
+ ui32ChunkSize * ui32NumPhysChunks,
+ &puiActualSize,
+ &pMapping,
+ uFlags,
+ pvPrivData,
+ ui32PrivDataLength,
+ IMG_NULL); /* We allocate VM space */
+
+ if (puiActualSize != ui32ChunkSize * ui32NumPhysChunks)
+ {
+ /*
+ Most likley the chunksize was not host page multiple so
+ return with an error
+ */
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: Failed to allocate memory for sparse allocation"));
+ BM_FreeMemory(pArena, IMG_NULL, pMapping);
+ return IMG_FALSE;
+ }
+
+ pMapping->uSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+ uSize = pMapping->uSizeVM;
+ pMapping->ui32ChunkSize = ui32ChunkSize;
+ pMapping->ui32NumVirtChunks = ui32NumVirtChunks;
+ pMapping->ui32NumPhysChunks = ui32NumPhysChunks;
+ pMapping->pabMapChunk = pabMapChunk;
+
+ /* Allocate VA space and map in the physical memory */
+ bSuccess = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ (IMG_UINT32)uDevVAddrAlignment,
+ &pMapping->DevVAddr);
+ if (!bSuccess)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "AllocMemory: Failed to allocate device memory"));
+ BM_FreeMemory(pArena, IMG_NULL, pMapping);
+ return IMG_FALSE;
+ }
- if (!RA_Alloc(pArena,
- uSize,
- IMG_NULL,
- (IMG_VOID*) &pMapping,
- uFlags,
- uDevVAddrAlignment,
- 0,
- (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
- {
- PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
- return IMG_FALSE;
+ /* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */
+ /* PRQA S 3356,3358 1 */
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+ pBuf->DevVAddr.uiAddr = pMapping->DevVAddr.uiAddr;
+ }
+ else
+ {
+ if (!RA_Alloc(pArena,
+ uSize,
+ IMG_NULL,
+ (IMG_VOID*) &pMapping,
+ uFlags,
+ uDevVAddrAlignment,
+ 0,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_UINTPTR_T *)&(pBuf->DevVAddr.uiAddr)))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: RA_Alloc(0x%x) FAILED", uSize));
+ return IMG_FALSE;
+ }
}
uOffset = pBuf->DevVAddr.uiAddr - pMapping->DevVAddr.uiAddr;
@@ -134,7 +252,7 @@ AllocMemory (BM_CONTEXT *pBMContext,
pBuf->CpuVAddr = IMG_NULL;
}
- if(uSize == pMapping->uSize)
+ if(uSize == pMapping->uSizeVM)
{
pBuf->hOSMemHandle = pMapping->hOSMemHandle;
}
@@ -151,7 +269,8 @@ AllocMemory (BM_CONTEXT *pBMContext,
}
}
-
+ /* for hm_contiguous and hm_wrapped memory, the pMapping
+ * will have a physical address, else 0 */
pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + uOffset;
if(uFlags & PVRSRV_MEM_ZERO)
@@ -166,7 +285,7 @@ AllocMemory (BM_CONTEXT *pBMContext,
{
if(uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
{
-
+ /* user supplied DevVAddr, no RAM backing */
PVR_ASSERT(psDevVAddr != IMG_NULL);
if (psDevVAddr == IMG_NULL)
@@ -175,7 +294,7 @@ AllocMemory (BM_CONTEXT *pBMContext,
return IMG_FALSE;
}
-
+ /* just make space in the pagetables */
pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
uSize,
IMG_NULL,
@@ -183,22 +302,30 @@ AllocMemory (BM_CONTEXT *pBMContext,
uDevVAddrAlignment,
psDevVAddr);
-
+ /* setup buf */
pBuf->DevVAddr = *psDevVAddr;
}
else
{
-
+ IMG_BOOL bResult;
+ /* BM supplied DevVAddr, no RAM Backing */
-
- pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
+ /* just make space in the pagetables */
+ bResult = pBMContext->psDeviceNode->pfnMMUAlloc (psBMHeap->pMMUHeap,
uSize,
IMG_NULL,
0,
uDevVAddrAlignment,
&pBuf->DevVAddr);
+
+ if(!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "AllocMemory: MMUAlloc failed"));
+ return IMG_FALSE;
+ }
}
-
+
+ /* allocate a mocked-up mapping */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (struct _BM_MAPPING_),
(IMG_PVOID *)&pMapping, IMG_NULL,
@@ -208,11 +335,12 @@ AllocMemory (BM_CONTEXT *pBMContext,
return IMG_FALSE;
}
-
+ /* setup buf */
pBuf->CpuVAddr = IMG_NULL;
pBuf->hOSMemHandle = 0;
pBuf->CpuPAddr.uiAddr = 0;
+ /* setup mapping */
pMapping->CpuVAddr = IMG_NULL;
pMapping->CpuPAddr.uiAddr = 0;
pMapping->DevVAddr = pBuf->DevVAddr;
@@ -221,16 +349,16 @@ AllocMemory (BM_CONTEXT *pBMContext,
pMapping->hOSMemHandle = 0;
}
-
+ /* Record the arena pointer in the mapping. */
pMapping->pArena = pArena;
pMapping->ui32DevVAddrAlignment = uDevVAddrAlignment;
pMapping->bUnmapped = IMG_FALSE;
-
+ /* record the heap */
pMapping->pBMHeap = psBMHeap;
pBuf->pMapping = pMapping;
-
+ /* output some stats */
PVR_DPF ((PVR_DBG_MESSAGE,
"AllocMemory: pMapping=%08x: DevV=%08X CpuV=%08x CpuP=%08X uSize=0x%x",
(IMG_UINTPTR_T)pMapping,
@@ -247,13 +375,34 @@ AllocMemory (BM_CONTEXT *pBMContext,
pBuf->CpuPAddr.uiAddr,
uSize));
-
+ /* Verify virtual device address alignment */
PVR_ASSERT(((pBuf->DevVAddr.uiAddr) & (uDevVAddrAlignment - 1)) == 0);
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function WrapMemory
+
+ @Description Allocate a buffer mapped into both cpu and device virtual
+ address spaces.
+
+ @Input psBMHeap - BM heap
+ @Input uSize - requested buffer size in bytes.
+ @Input ui32BaseOffset - Offset from page of wrap.
+ @Input bPhysContig - Is the wrap physically contiguous.
+ @Input psAddr - List of pages to wrap.
+ @Input pvCPUVAddr - Optional CPU Kernel virtual address (page aligned) of memory to wrap
+ @Input uFlags - property flags for the buffer.
+ @Output Buf - receives a pointer to a descriptor of the allocated
+ buffer.
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed.
+
+ *****************************************************************************/
static IMG_BOOL
WrapMemory (BM_HEAP *psBMHeap,
IMG_SIZE_T uSize,
@@ -274,13 +423,13 @@ WrapMemory (BM_HEAP *psBMHeap,
(IMG_UINTPTR_T)psBMHeap, uSize, ui32BaseOffset, bPhysContig, (IMG_UINTPTR_T)pvCPUVAddr, uFlags));
PVR_ASSERT((psAddr->uiAddr & (ui32PageSize - 1)) == 0);
-
+ /* Only need lower 12 bits of the cpu addr - don't care what size a void* is */
PVR_ASSERT(((IMG_UINTPTR_T)pvCPUVAddr & (ui32PageSize - 1)) == 0);
uSize += ui32BaseOffset;
uSize = HOST_PAGEALIGN (uSize);
-
+ /* allocate a mocked-up mapping */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*pMapping),
(IMG_PVOID *)&pMapping, IMG_NULL,
@@ -293,6 +442,7 @@ WrapMemory (BM_HEAP *psBMHeap,
OSMemSet(pMapping, 0, sizeof (*pMapping));
pMapping->uSize = uSize;
+ pMapping->uSizeVM = uSize;
pMapping->pBMHeap = psBMHeap;
pMapping->bUnmapped = IMG_FALSE;
@@ -343,6 +493,7 @@ WrapMemory (BM_HEAP *psBMHeap,
if(OSReservePhys(pMapping->CpuPAddr,
pMapping->uSize,
uFlags,
+ IMG_NULL,
&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
@@ -369,7 +520,9 @@ WrapMemory (BM_HEAP *psBMHeap,
}
}
-
+ /*
+ * Allocate device memory for this buffer. Map wrapped pages as read/write
+ */
bResult = DevMemoryAlloc(psBMHeap->pBMContext,
pMapping,
IMG_NULL,
@@ -384,7 +537,12 @@ WrapMemory (BM_HEAP *psBMHeap,
goto fail_cleanup;
}
-
+ /*
+ * Determine the offset of this allocation within the underlying
+ * dual mapped chunk of memory, we can assume that all three
+ * addresses associated with this allocation are placed at the same
+ * offset within the underlying chunk.
+ */
pBuf->CpuPAddr.uiAddr = pMapping->CpuPAddr.uiAddr + ui32BaseOffset;
if(!ui32BaseOffset)
{
@@ -456,7 +614,7 @@ fail_cleanup:
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_FALSE;
}
@@ -497,14 +655,18 @@ ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui3
IMG_SIZE_T ui32CurrentOffset = 0;
IMG_CPU_PHYADDR CpuPAddr;
-
+ /* Walk through the pBuf one page at a time and use
+ * transient mappings to zero the memory */
+
PVR_ASSERT(pBuf->hOSMemHandle);
while(ui32BytesRemaining > 0)
{
IMG_SIZE_T ui32BlockBytes = MIN(ui32BytesRemaining, HOST_PAGESIZE());
CpuPAddr = OSMemHandleToCpuPAddr(pBuf->hOSMemHandle, ui32CurrentOffset);
-
+ /* If the CpuPAddr isn't page aligned then start by writing up to the next page
+ * boundary (or ui32BytesRemaining if less), so that subsequent iterations can
+ * copy full physical pages. */
if(CpuPAddr.uiAddr & (HOST_PAGESIZE() -1))
{
ui32BlockBytes =
@@ -536,6 +698,26 @@ ZeroBuf(BM_BUF *pBuf, BM_MAPPING *pMapping, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui3
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function FreeBuf
+
+ @Description Free a buffer previously allocated with BM_Alloc() or unwrap
+ one previous wrapped with BM_Wrap().
+ The buffer is identified by the buffer descriptor pBuf
+ returned at allocation. Note the double indirection when
+ passing the buffer.
+
+
+ @Input pBuf - buffer descriptor to free.
+ @Input ui32Flags - flags
+ @Input bFromAllocator - Is this being called by the
+ allocator?
+
+ @Return None.
+
+ *****************************************************************************/
static IMG_VOID
FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
{
@@ -547,7 +729,7 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
(IMG_UINTPTR_T)pBuf, pBuf->DevVAddr.uiAddr,
(IMG_UINTPTR_T)pBuf->CpuVAddr, pBuf->CpuPAddr.uiAddr));
-
+ /* record mapping */
pMapping = pBuf->pMapping;
psDeviceNode = pMapping->pBMHeap->pBMContext->psDeviceNode;
@@ -558,32 +740,31 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
if(ui32Flags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR)
{
-
+ /* Submemhandle is required by exported mappings */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
+ /* user supplied Device Virtual Address */
if(ui32Flags & PVRSRV_MEM_RAM_BACKED_ALLOCATION)
{
-
+ /* RAM backed allocation */
PVR_DPF ((PVR_DBG_ERROR, "FreeBuf: combination of DevVAddr management and RAM backing mode unsupported"));
}
else
{
-
+ /* free the mocked-up mapping */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
- pBuf->pMapping = IMG_NULL;
+ pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/
}
}
}
else
{
-
+ /* BM supplied Device Virtual Address */
if(pBuf->hOSMemHandle != pMapping->hOSMemHandle)
{
-
+ /* Submemhandle is required by exported mappings */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
OSReleaseSubMemHandle(pBuf->hOSMemHandle, ui32Flags);
}
}
@@ -592,7 +773,7 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
/* see comment below */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
- PVR_ASSERT(pBuf->ui32ExportCount == 0)
+ PVR_ASSERT(pBuf->ui32ExportCount == 0);
BM_FreeMemory(pMapping->pBMHeap, 0, pMapping);
}
}
@@ -602,13 +783,30 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
* need to change the one above in PVRSRV_HAP_GPU_PAGEABLE
* case.. see comments in unstripped driver
*/
+ /* Submemhandle is required by exported mappings */
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
-
-
- PVR_ASSERT(pBuf->ui32ExportCount == 0)
- RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ /*
+ RAM backed allocation
+ Note: currently no need to distinguish between hm_env and hm_contiguous
+ */
+ PVR_ASSERT(pBuf->ui32ExportCount == 0);
+ if (pBuf->pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ IMG_UINT32 ui32FreeSize = sizeof(IMG_BOOL) * pBuf->pMapping->ui32NumVirtChunks;
+ IMG_PVOID pvFreePtr = pBuf->pMapping->pabMapChunk;
+
+ /* With sparse allocations we don't go through the sub-alloc RA */
+ BM_FreeMemory(pBuf->pMapping->pBMHeap, pBuf->DevVAddr.uiAddr, pBuf->pMapping);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ ui32FreeSize,
+ pvFreePtr,
+ IMG_NULL);
+ }
+ else
+ {
+ RA_Free (pBuf->pMapping->pArena, pBuf->DevVAddr.uiAddr, IMG_FALSE);
+ }
}
}
else
@@ -638,9 +836,9 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
-
+ /* free the mocked-up mapping */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
- pBuf->pMapping = IMG_NULL;
+ pBuf->pMapping = IMG_NULL; /*nulling pointer alias*/
}
}
}
@@ -649,10 +847,22 @@ FreeBuf (BM_BUF *pBuf, IMG_UINT32 ui32Flags, IMG_BOOL bFromAllocator)
if ((pBuf->ui32ExportCount == 0) && (pBuf->ui32RefCount == 0))
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_BUF), pBuf, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContext_AnyCb
+
+ @Description Destroy a buffer manager heap.
+
+ @Input psBMHeap
+
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
{
if(psBMHeap->ui32Attribs
@@ -673,6 +883,20 @@ static PVRSRV_ERROR BM_DestroyContext_AnyCb(BM_HEAP *psBMHeap)
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContext
+
+ @Description Destroy a buffer manager context. All allocated buffers must be
+ free'd before calling this function. This function is called
+ also to perform cleanup during aborted initialisations so it's
+ fairly careful not to assume any given resource has really been
+ created/allocated.
+
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
PVRSRV_ERROR
BM_DestroyContext(IMG_HANDLE hBMContext,
IMG_BOOL *pbDestroyed)
@@ -687,8 +911,9 @@ BM_DestroyContext(IMG_HANDLE hBMContext,
*pbDestroyed = IMG_FALSE;
}
-
-
+ /*
+ Exit straight away if it's an invalid context handle
+ */
if (pBMContext == IMG_NULL)
{
PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Invalid handle"));
@@ -699,34 +924,23 @@ BM_DestroyContext(IMG_HANDLE hBMContext,
if (pBMContext->ui32RefCount > 0)
{
-
+ /* Just return if there are more references to this context */
return PVRSRV_OK;
}
-
-
-
+ /*
+ Check whether there is a bug in the client which brought it here before
+ all the allocations have been freed.
+ */
eError = List_BM_HEAP_PVRSRV_ERROR_Any(pBMContext->psBMHeap, &BM_DestroyContext_AnyCb);
if(eError != PVRSRV_OK)
{
PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: List_BM_HEAP_PVRSRV_ERROR_Any failed"));
-#if 0
-
-
-
-
- PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: Cleaning up with ResManFreeSpecial"));
- if(ResManFreeSpecial() != PVRSRV_OK)
- {
- PVR_DPF ((PVR_DBG_ERROR, "BM_DestroyContext: ResManFreeSpecial failed %d",eError));
- }
-
-#endif
return eError;
}
else
{
-
+ /* free the device memory context */
eError = ResManFreeResByPtr(pBMContext->hResItem, CLEANUP_WITH_POLL);
if(eError != PVRSRV_OK)
{
@@ -734,7 +948,7 @@ BM_DestroyContext(IMG_HANDLE hBMContext,
return eError;
}
-
+ /* mark context as destroyed */
if (pbDestroyed != IMG_NULL)
{
*pbDestroyed = IMG_TRUE;
@@ -745,12 +959,25 @@ BM_DestroyContext(IMG_HANDLE hBMContext,
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContextCallBack_AnyVaCb
+
+ @Description Destroy Device memory context
+
+ @Input psBMHeap - heap to be freed.
+ @Input va - list of variable arguments with the following contents:
+ - psDeviceNode
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
{
PVRSRV_DEVICE_NODE *psDeviceNode;
psDeviceNode = va_arg(va, PVRSRV_DEVICE_NODE*);
-
+ /* Free up the import arenas */
if(psBMHeap->ui32Attribs
& (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
@@ -766,17 +993,30 @@ static PVRSRV_ERROR BM_DestroyContextCallBack_AnyVaCb(BM_HEAP *psBMHeap, va_list
return PVRSRV_ERROR_UNSUPPORTED_BACKING_STORE;
}
-
+ /* Free up the MMU Heaps */
psDeviceNode->pfnMMUDelete(psBMHeap->pMMUHeap);
-
+ /* Free Heap memory */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyContextCallBack
+
+ @Description Destroy Device memory context
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+
+ @Return PVRSRV_ERROR
+
+ *****************************************************************************/
static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
@@ -784,15 +1024,20 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
BM_CONTEXT *pBMContext = pvParam;
PVRSRV_DEVICE_NODE *psDeviceNode;
PVRSRV_ERROR eError;
+/* BM_CONTEXT **ppBMContext;
+ BM_HEAP *psBMHeap, *psTmpBMHeap;*/
+
PVR_UNREFERENCED_PARAMETER(ui32Param);
PVR_UNREFERENCED_PARAMETER(bDummy);
-
-
+ /*
+ Get DeviceNode from BMcontext
+ */
psDeviceNode = pBMContext->psDeviceNode;
-
-
+ /*
+ Free the import arenas and heaps
+ */
eError = List_BM_HEAP_PVRSRV_ERROR_Any_va(pBMContext->psBMHeap,
&BM_DestroyContextCallBack_AnyVaCb,
psDeviceNode);
@@ -800,15 +1045,17 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
{
return eError;
}
-
-
+ /*
+ 'Finalise' the MMU
+ */
if (pBMContext->psMMUContext)
{
psDeviceNode->pfnMMUFinalise(pBMContext->psMMUContext);
}
-
-
+ /*
+ Free up generic, useful resources - if they were allocated.
+ */
if (pBMContext->pBufferHash)
{
HASH_Delete(pBMContext->pBufferHash);
@@ -816,20 +1063,22 @@ static PVRSRV_ERROR BM_DestroyContextCallBack(IMG_PVOID pvParam,
if (pBMContext == psDeviceNode->sDevMemoryInfo.pBMKernelContext)
{
-
+ /* Freeing the kernel context */
psDeviceNode->sDevMemoryInfo.pBMKernelContext = IMG_NULL;
}
else
{
if (pBMContext->ppsThis != IMG_NULL)
{
-
+ /*
+ * Remove context from the linked list
+ */
List_BM_CONTEXT_Remove(pBMContext);
}
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_CONTEXT), pBMContext, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
@@ -841,7 +1090,7 @@ static IMG_HANDLE BM_CreateContext_IncRefCount_AnyVaCb(BM_CONTEXT *pBMContext, v
hResManContext = va_arg(va, PRESMAN_CONTEXT);
if(ResManFindResourceByPtr(hResManContext, pBMContext->hResItem) == PVRSRV_OK)
{
-
+ /* just increment the refcount and return the memory context found for this process */
pBMContext->ui32RefCount++;
return pBMContext;
}
@@ -859,13 +1108,25 @@ static IMG_VOID BM_CreateContext_InsertHeap_ForEachVaCb(BM_HEAP *psBMHeap, va_li
case DEVICE_MEMORY_HEAP_SHARED:
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* insert the heap into the device's MMU page directory/table */
psDeviceNode->pfnMMUInsertHeap(pBMContext->psMMUContext, psBMHeap->pMMUHeap);
break;
}
}
}
+/*!
+******************************************************************************
+
+ @Function BM_CreateContext
+
+ @Description Creates and initialises a buffer manager context. This function must be called
+ before any other buffer manager functions.
+
+ @Return valid BM context handle - Success
+ IMG_NULL - Failed
+
+ *****************************************************************************/
IMG_HANDLE
BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_PHYADDR *psPDDevPAddr,
@@ -873,6 +1134,7 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_BOOL *pbCreated)
{
BM_CONTEXT *pBMContext;
+/* BM_HEAP *psBMHeap;*/
DEVICE_MEMORY_INFO *psDevMemoryInfo;
IMG_BOOL bKernelContext;
PRESMAN_CONTEXT hResManContext;
@@ -895,7 +1157,7 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
*pbCreated = IMG_FALSE;
}
-
+ /* setup the device memory info. */
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
if (bKernelContext == IMG_FALSE)
@@ -909,7 +1171,7 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
}
}
-
+ /* allocate a BM context */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (struct _BM_CONTEXT_),
(IMG_PVOID *)&pBMContext, IMG_NULL,
@@ -920,11 +1182,11 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
}
OSMemSet(pBMContext, 0, sizeof (BM_CONTEXT));
-
+ /* store the associated devicenode */
pBMContext->psDeviceNode = psDeviceNode;
-
-
+ /* This hash table is used to store BM_Wraps in a global way */
+ /* INTEGRATION_POINT: 32 is an abitrary limit on the number of hashed BM_wraps */
pBMContext->pBufferHash = HASH_Create(32);
if (pBMContext->pBufferHash==IMG_NULL)
{
@@ -942,17 +1204,18 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
if(bKernelContext)
{
-
+ /* just save the kernel context */
PVR_ASSERT(psDevMemoryInfo->pBMKernelContext == IMG_NULL);
psDevMemoryInfo->pBMKernelContext = pBMContext;
}
else
{
-
-
-
-
-
+ /*
+ On the creation of each new context we must
+ insert the kernel context's 'shared' and 'shared_exported'
+ heaps into the new context
+ - check the kernel context and heaps exist
+ */
PVR_ASSERT(psDevMemoryInfo->pBMKernelContext);
if (psDevMemoryInfo->pBMKernelContext == IMG_NULL)
@@ -963,28 +1226,30 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
PVR_ASSERT(psDevMemoryInfo->pBMKernelContext->psBMHeap);
-
-
-
-
+ /*
+ insert the kernel heaps structures into the new context's shared heap list
+ Note. this will include the kernel only heaps but these will not actually
+ be imported into the context nor returned to the client
+ */
pBMContext->psBMSharedHeap = psDevMemoryInfo->pBMKernelContext->psBMHeap;
-
-
-
+ /*
+ insert the shared heaps into the MMU page directory/table
+ for the new context
+ */
List_BM_HEAP_ForEach_va(pBMContext->psBMSharedHeap,
&BM_CreateContext_InsertHeap_ForEachVaCb,
psDeviceNode,
pBMContext);
-
+ /* Finally, insert the new context into the list of BM contexts */
List_BM_CONTEXT_Insert(&psDevMemoryInfo->pBMContext, pBMContext);
}
-
+ /* Increment the refcount, as creation is successful */
pBMContext->ui32RefCount++;
-
+ /* register with resman */
pBMContext->hResItem = ResManRegisterRes(hResManContext,
RESMAN_TYPE_DEVICEMEM_CONTEXT,
pBMContext,
@@ -1015,7 +1280,7 @@ static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
psDevMemHeapInfo = va_arg(va, DEVICE_MEMORY_HEAP_INFO*);
if (psBMHeap->sDevArena.ui32HeapID == psDevMemHeapInfo->ui32HeapID)
{
-
+ /* Match - just return already created heap */
return psBMHeap;
}
else
@@ -1024,6 +1289,19 @@ static IMG_VOID *BM_CreateHeap_AnyVaCb(BM_HEAP *psBMHeap, va_list va)
}
}
+/*!
+******************************************************************************
+
+ @Function BM_CreateHeap
+
+ @Description Creates and initialises a BM heap for a given BM context.
+
+ @Return
+ valid heap handle - success
+ IMG_NULL - failure
+
+
+ *****************************************************************************/
IMG_HANDLE
BM_CreateHeap (IMG_HANDLE hBMContext,
DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo)
@@ -1042,16 +1320,18 @@ BM_CreateHeap (IMG_HANDLE hBMContext,
psDeviceNode = pBMContext->psDeviceNode;
-
-
+ /*
+ * Ensure that the heap size is a multiple of the data page size.
+ */
PVR_ASSERT((psDevMemHeapInfo->ui32HeapSize & (psDevMemHeapInfo->ui32DataPageSize - 1)) == 0);
PVR_ASSERT(psDevMemHeapInfo->ui32HeapSize > 0);
-
-
-
-
-
+ /*
+ We may be being asked to create a heap in a context which already has one.
+ Test for refcount > 0 because PVRSRVGetDeviceMemHeapInfoKM doesn't increment the refcount.
+ This does mean that the first call to PVRSRVCreateDeviceMemContextKM will first try to find
+ heaps that we already know don't exist
+ */
if(pBMContext->ui32RefCount > 0)
{
psBMHeap = (BM_HEAP*)List_BM_HEAP_Any_va(pBMContext->psBMHeap,
@@ -1084,8 +1364,11 @@ BM_CreateHeap (IMG_HANDLE hBMContext,
psBMHeap->sDevArena.ui32DataPageSize = psDevMemHeapInfo->ui32DataPageSize;
psBMHeap->sDevArena.psDeviceMemoryHeapInfo = psDevMemHeapInfo;
psBMHeap->ui32Attribs = psDevMemHeapInfo->ui32Attribs;
+#if defined(SUPPORT_MEMORY_TILING)
+ psBMHeap->ui32XTileStride = psDevMemHeapInfo->ui32XTileStride;
+#endif
-
+ /* tie the heap to the context */
psBMHeap->pBMContext = pBMContext;
psBMHeap->pMMUHeap = psDeviceNode->pfnMMUCreate (pBMContext->psMMUContext,
@@ -1098,7 +1381,7 @@ BM_CreateHeap (IMG_HANDLE hBMContext,
goto ErrorExit;
}
-
+ /* memory is allocated from the OS as required */
psBMHeap->pImportArena = RA_Create (psDevMemHeapInfo->pszBSName,
0, 0, IMG_NULL,
MAX(HOST_PAGESIZE(), psBMHeap->sDevArena.ui32DataPageSize),
@@ -1114,10 +1397,11 @@ BM_CreateHeap (IMG_HANDLE hBMContext,
if(psBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
{
-
-
-
-
+ /*
+ memory comes from a device memory contiguous allocator (ra)
+ Note: these arenas are shared across the system so don't delete
+ as part of heap destroy
+ */
psBMHeap->pLocalDevMemArena = psDevMemHeapInfo->psLocalDevMemArena;
if(psBMHeap->pLocalDevMemArena == IMG_NULL)
{
@@ -1126,28 +1410,41 @@ BM_CreateHeap (IMG_HANDLE hBMContext,
}
}
-
+ /* insert heap into head of the heap list */
List_BM_HEAP_Insert(&pBMContext->psBMHeap, psBMHeap);
return (IMG_HANDLE)psBMHeap;
-
+ /* handle error case */
ErrorExit:
-
+ /* Free up the MMU if we created one */
if (psBMHeap->pMMUHeap != IMG_NULL)
{
psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
-
+ /* don't finalise psMMUContext as we don't own it */
}
-
+ /* Free the Heap memory */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function BM_DestroyHeap
+
+ @Description Destroys a BM heap
+
+ @Return
+ valid heap handle - success
+ IMG_NULL - failure
+
+
+ *****************************************************************************/
IMG_VOID
BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
{
@@ -1158,7 +1455,7 @@ BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
if(psBMHeap)
{
-
+ /* Free up the import arenas */
if(psBMHeap->ui32Attribs
& (PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG
|PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG))
@@ -1174,14 +1471,12 @@ BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
return;
}
-
+ /* Free up the MMU Heap */
psDeviceNode->pfnMMUDelete (psBMHeap->pMMUHeap);
-
+ /* remove from the heap list */
List_BM_HEAP_Remove(psBMHeap);
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_HEAP), psBMHeap, IMG_NULL);
-
}
else
{
@@ -1190,6 +1485,17 @@ BM_DestroyHeap (IMG_HANDLE hDevMemHeap)
}
+/*!
+******************************************************************************
+
+ @Function BM_Reinitialise
+
+ @Description Reinitialise the buffer manager after a power down event.
+
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed
+
+ *****************************************************************************/
IMG_BOOL
BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
{
@@ -1197,16 +1503,48 @@ BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode)
PVR_DPF((PVR_DBG_MESSAGE, "BM_Reinitialise"));
PVR_UNREFERENCED_PARAMETER(psDeviceNode);
+ /* FIXME: Need to reenable all contexts
+ List_BM_CONTEXT_ForEach(psDeviceNode->sDevMemoryInfo.pBMContext, MMU_Enable);
+ */
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function BM_Alloc
+
+ @Description Allocate a buffer mapped into both cpu and device virtual
+ memory maps.
+
+ @Input hDevMemHeap
+ @Input psDevVAddr - device virtual address specified by caller (optional)
+ @Input uSize - require size in bytes of the buffer.
+ @Input pui32Flags - bit mask of buffer property flags.
+ @Input uDevVAddrAlignment - required alignment in bytes, or 0.
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+
+ @Output phBuf - receives buffer handle
+ @Output pui32Flags - bit mask of heap property flags.
+
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failure
+
+ *****************************************************************************/
IMG_BOOL
BM_Alloc ( IMG_HANDLE hDevMemHeap,
IMG_DEV_VIRTADDR *psDevVAddr,
IMG_SIZE_T uSize,
IMG_UINT32 *pui32Flags,
IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
BM_HANDLE *phBuf)
{
BM_BUF *pBuf;
@@ -1238,7 +1576,9 @@ BM_Alloc ( IMG_HANDLE hDevMemHeap,
uDevVAddrAlignment = 1;
}
-
+ /*
+ * Allocate something in which to record the allocation's details.
+ */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (BM_BUF),
(IMG_PVOID *)&pBuf, IMG_NULL,
@@ -1249,17 +1589,25 @@ BM_Alloc ( IMG_HANDLE hDevMemHeap,
}
OSMemSet(pBuf, 0, sizeof (BM_BUF));
-
+ /*
+ * Allocate the memory itself now.
+ */
if (AllocMemory(pBMContext,
psBMHeap,
psDevVAddr,
uSize,
uFlags,
uDevVAddrAlignment,
+ pvPrivData,
+ ui32PrivDataLength,
+ ui32ChunkSize,
+ ui32NumVirtChunks,
+ ui32NumPhysChunks,
+ pabMapChunk,
pBuf) != IMG_TRUE)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
-
+ /* not nulling pointer, out of scope */
PVR_DPF((PVR_DBG_ERROR, "BM_Alloc: AllocMemory FAILED"));
return IMG_FALSE;
}
@@ -1268,12 +1616,17 @@ BM_Alloc ( IMG_HANDLE hDevMemHeap,
"BM_Alloc (uSize=0x%x, uFlags=0x%x)",
uSize, uFlags));
-
+ /*
+ * Assign the handle and return.
+ */
pBuf->ui32RefCount = 1;
*phBuf = (BM_HANDLE)pBuf;
*pui32Flags = uFlags | psBMHeap->ui32Attribs;
-
+ /*
+ * If the user has specified heap CACHETYPE flags themselves,
+ * override any CACHETYPE flags inherited from the heap.
+ */
if(uFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
*pui32Flags &= ~PVRSRV_HAP_CACHETYPE_MASK;
@@ -1286,6 +1639,21 @@ BM_Alloc ( IMG_HANDLE hDevMemHeap,
#if defined(PVR_LMA)
+/*!
+******************************************************************************
+
+ @Function ValidSysPAddrArrayForDev
+
+ @Description Verify the array of system address is accessible
+ by the given device.
+
+ @Input psDeviceNode
+ @Input psSysPAddr - system address array
+ @Input ui32PageSize - size of address array
+
+ @Return IMG_BOOL
+
+ *****************************************************************************/
static IMG_BOOL
ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSysPAddr, IMG_UINT32 ui32PageCount, IMG_SIZE_T ui32PageSize)
{
@@ -1312,6 +1680,21 @@ ValidSysPAddrArrayForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR *psSy
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function ValidSysPAddrRangeForDev
+
+ @Description Verify a system address range is accessible
+ by the given device.
+
+ @Input psDeviceNode
+ @Input sStartSysPAddr - starting system address
+ @Input ui32Range - length of address range
+
+ @Return IMG_BOOL
+
+ *****************************************************************************/
static IMG_BOOL
ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStartSysPAddr, IMG_SIZE_T ui32Range)
{
@@ -1339,6 +1722,28 @@ ValidSysPAddrRangeForDev(PVRSRV_DEVICE_NODE *psDeviceNode, IMG_SYS_PHYADDR sStar
#endif
+/*!
+******************************************************************************
+
+ @Function BM_Wrap
+
+ @Description Create a buffer which wraps user provided system physical
+ memory.
+ The wrapped memory must be page aligned. BM_Wrap will
+ roundup the size to a multiple of cpu pages.
+
+ @Input ui32Size - size of memory to wrap.
+ @Input ui32Offset - Offset into page of memory to wrap.
+ @Input bPhysContig - Is the wrap physically contiguous.
+ @Input psSysAddr - list of system physical page addresses of memory to wrap.
+ @Input pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap.
+ @Input uFlags - bit mask of buffer property flags.
+ @output phBuf - receives the buffer handle.
+
+ @Return IMG_TRUE - Success.
+ IMG_FALSE - Failed
+
+ *****************************************************************************/
IMG_BOOL
BM_Wrap ( IMG_HANDLE hDevMemHeap,
IMG_SIZE_T ui32Size,
@@ -1393,20 +1798,23 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap,
}
}
#endif
-
+ /*
+ * Insert the System Physical Address of the first page into the hash so we can optimise multiple wraps of the
+ * same memory.
+ */
sHashAddress = psSysAddr[0];
-
+ /* Add the in-page offset to ensure a unique hash */
sHashAddress.uiAddr += ui32Offset;
-
+ /* See if this address has already been wrapped */
pBuf = (BM_BUF *)HASH_Retrieve(psBMContext->pBufferHash, sHashAddress.uiAddr);
if(pBuf)
{
IMG_SIZE_T ui32MappingSize = HOST_PAGEALIGN (ui32Size + ui32Offset);
-
+ /* Check base address, size and contiguity type match */
if(pBuf->pMapping->uSize == ui32MappingSize && (pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped ||
pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr))
{
@@ -1414,7 +1822,7 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap,
"BM_Wrap (Matched previous Wrap! uSize=0x%x, uOffset=0x%x, SysAddr=%08X)",
ui32Size, ui32Offset, sHashAddress.uiAddr));
- pBuf->ui32RefCount++;
+ PVRSRVBMBufIncRef(pBuf);
*phBuf = (BM_HANDLE)pBuf;
if(pui32Flags)
*pui32Flags = uFlags;
@@ -1423,12 +1831,15 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap,
}
else
{
-
+ /* Otherwise removed that item from the hash table
+ (a workaround for buffer device class) */
HASH_Remove(psBMContext->pBufferHash, (IMG_UINTPTR_T)sHashAddress.uiAddr);
}
}
-
+ /*
+ * Allocate something in which to record the allocation's details.
+ */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof (BM_BUF),
(IMG_PVOID *)&pBuf, IMG_NULL,
@@ -1439,19 +1850,23 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap,
}
OSMemSet(pBuf, 0, sizeof (BM_BUF));
-
+ /*
+ * Actually perform the memory wrap.
+ */
if (WrapMemory (psBMHeap, ui32Size, ui32Offset, bPhysContig, psSysAddr, pvCPUVAddr, uFlags, pBuf) != IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "BM_Wrap: WrapMemory FAILED"));
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof (BM_BUF), pBuf, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_FALSE;
}
-
+ /* Only insert the buffer in the hash table if it is contiguous - allows for optimisation of multiple wraps
+ * of the same contiguous buffer.
+ */
if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
{
-
+ /* Have we calculated the right Hash key ? */
PVR_ASSERT(SysSysPAddrToCpuPAddr(sHashAddress).uiAddr == pBuf->CpuPAddr.uiAddr);
if (!HASH_Insert (psBMContext->pBufferHash, sHashAddress.uiAddr, (IMG_UINTPTR_T)pBuf))
@@ -1466,36 +1881,73 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap,
"BM_Wrap (uSize=0x%x, uFlags=0x%x, devVAddr=%08X)",
ui32Size, uFlags, pBuf->DevVAddr.uiAddr));
-
+ /*
+ * Assign the handle and return.
+ */
pBuf->ui32RefCount = 1;
*phBuf = (BM_HANDLE)pBuf;
if(pui32Flags)
{
-
+ /* need to override the heap attributes SINGLE PROC to MULT_PROC. */
*pui32Flags = (uFlags & ~PVRSRV_HAP_MAPTYPE_MASK) | PVRSRV_HAP_MULTI_PROCESS;
}
return IMG_TRUE;
}
+/*!
+******************************************************************************
+
+ @Function BM_Export
+
+ @Description Export a buffer previously allocated via BM_Alloc.
+
+ @Input hBuf - buffer handle.
+ @Input ui32Flags - flags
+
+ @Return None.
+
+ *****************************************************************************/
+
IMG_VOID
BM_Export (BM_HANDLE hBuf)
{
BM_BUF *pBuf = (BM_BUF *)hBuf;
- pBuf->ui32ExportCount++;
+ PVRSRVBMBufIncExport(pBuf);
}
+/*!
+******************************************************************************
+ @Function BM_Export
+
+ @Description Export a buffer previously allocated via BM_Alloc.
+
+ @Input hBuf - buffer handle.
+
+ @Return None.
+**************************************************************************/
IMG_VOID
BM_FreeExport(BM_HANDLE hBuf,
IMG_UINT32 ui32Flags)
{
BM_BUF *pBuf = (BM_BUF *)hBuf;
- pBuf->ui32ExportCount--;
+ PVRSRVBMBufDecExport(pBuf);
FreeBuf (pBuf, ui32Flags, IMG_FALSE);
}
+/*!
+******************************************************************************
+ @Function BM_FreeExport
+
+ @Description Free a buffer previously exported via BM_Export.
+
+ @Input hBuf - buffer handle.
+ @Input ui32Flags - flags
+
+ @Return None.
+**************************************************************************/
IMG_VOID
BM_Free (BM_HANDLE hBuf,
IMG_UINT32 ui32Flags)
@@ -1515,8 +1967,7 @@ BM_Free (BM_HANDLE hBuf,
SysAcquireData(&psSysData);
- pBuf->ui32RefCount--;
-
+ PVRSRVBMBufDecRef(pBuf);
if(pBuf->ui32RefCount == 0)
{
if(pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped || pBuf->pMapping->eCpuMemoryOrigin == hm_wrapped_virtaddr)
@@ -1530,21 +1981,6 @@ BM_Free (BM_HANDLE hBuf,
}
-IMG_VOID
-BM_RegisterSmart(BM_HANDLE hBuf, IMG_HANDLE hSmartCache)
-{
- BM_BUF *pBuf = (BM_BUF *)hBuf;
- OSMemHandleRegisterSmart(pBuf->hOSMemHandle, hSmartCache);
-}
-
-IMG_VOID
-BM_UnregisterSmart(BM_HANDLE hBuf, IMG_HANDLE hSmartCache)
-{
- BM_BUF *pBuf = (BM_BUF *)hBuf;
- OSMemHandleUnegisterSmart(pBuf->hOSMemHandle, hSmartCache);
-}
-
-
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
IMG_VOID
BM_SetGEM(BM_HANDLE hBuf, IMG_HANDLE buf)
@@ -1561,7 +1997,18 @@ BM_GetGEM(BM_HANDLE hBuf)
}
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
+/*!
+******************************************************************************
+ @Function BM_HandleToCpuVaddr
+
+ @Description Retreive the cpu virtual address associated with a buffer.
+
+ @Input buffer handle.
+
+ @Return buffers cpu virtual address, or NULL if none exists
+
+ *****************************************************************************/
IMG_CPU_VIRTADDR
BM_HandleToCpuVaddr (BM_HANDLE hBuf)
{
@@ -1581,6 +2028,18 @@ BM_HandleToCpuVaddr (BM_HANDLE hBuf)
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToDevVaddr
+
+ @Description Retreive the device virtual address associated with a buffer.
+
+ @Input hBuf - buffer handle.
+
+ @Return buffers device virtual address.
+
+ *****************************************************************************/
IMG_DEV_VIRTADDR
BM_HandleToDevVaddr (BM_HANDLE hBuf)
{
@@ -1599,6 +2058,18 @@ BM_HandleToDevVaddr (BM_HANDLE hBuf)
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToSysPaddr
+
+ @Description Retreive the system physical address associated with a buffer.
+
+ @Input hBuf - buffer handle.
+
+ @Return buffers device virtual address.
+
+ *****************************************************************************/
IMG_SYS_PHYADDR
BM_HandleToSysPaddr (BM_HANDLE hBuf)
{
@@ -1617,6 +2088,18 @@ BM_HandleToSysPaddr (BM_HANDLE hBuf)
return SysCpuPAddrToSysPAddr (pBuf->CpuPAddr);
}
+/*!
+******************************************************************************
+
+ @Function BM_HandleToMemOSHandle
+
+ @Description Retreive the underlying memory handle associated with a buffer.
+
+ @Input hBuf - buffer handle.
+
+ @Return OS Specific memory handle.
+
+ *****************************************************************************/
IMG_HANDLE
BM_HandleToOSMemHandle(BM_HANDLE hBuf)
{
@@ -1742,6 +2225,33 @@ BM_RemapToDev(BM_HANDLE hBuf)
}
+/*!
+******************************************************************************
+
+ @Function DevMemoryAlloc
+
+ @Description Allocate device memory for a given physical/virtual memory
+ mapping. We handle the main cases where device MMU mappings
+ are required - these are the dynamic cases: all wrappings of
+ host OS memory and host OS imports for SYS_MMU_NORMAL mode.
+
+ If no MMU support is required then we simply map device virtual
+ space as device physical space.
+
+ @Input pBMContext - the pager to allocate from.
+ @Output pMapping - the mapping descriptor to be filled in for this
+ allocation.
+ @Output pActualSize - the actual size of the block allocated in
+ bytes.
+ @Input uFlags - allocation flags
+ @Input dev_vaddr_alignment - required device virtual address
+ alignment, or 0.
+ @Output pDevVAddr - receives the device virtual base address of the
+ allocated block.
+ @Return IMG_TRUE - Success
+ IMG_FALSE - Failed.
+
+ *****************************************************************************/
static IMG_BOOL
DevMemoryAlloc (BM_CONTEXT *pBMContext,
BM_MAPPING *pMapping,
@@ -1771,14 +2281,16 @@ DevMemoryAlloc (BM_CONTEXT *pBMContext,
#ifdef PDUMP
if(uFlags & PVRSRV_MEM_DUMMY)
{
-
+ /* only one page behind a dummy allocation */
ui32PDumpSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
}
#endif
-
+ /* Check we haven't fall through a gap */
+ PVR_ASSERT(pMapping->uSizeVM != 0);
+ /* allocate device linear space */
if (!psDeviceNode->pfnMMUAlloc (pMapping->pBMHeap->pMMUHeap,
- pMapping->uSize,
+ pMapping->uSizeVM,
pActualSize,
0,
dev_vaddr_alignment,
@@ -1793,7 +2305,7 @@ DevMemoryAlloc (BM_CONTEXT *pBMContext,
#endif
#if defined(PDUMP)
-
+ /* pdump the memory allocate */
PDUMPMALLOCPAGES(&psDeviceNode->sDevId,
pMapping->DevVAddr.uiAddr,
pMapping->CpuVAddr,
@@ -1803,8 +2315,8 @@ DevMemoryAlloc (BM_CONTEXT *pBMContext,
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
psDeviceNode->pfnMMUIsHeapShared(pMapping->pBMHeap->pMMUHeap),
#else
- IMG_FALSE,
-#endif
+ IMG_FALSE, // unused
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
(IMG_HANDLE)pMapping);
#endif
@@ -1814,26 +2326,61 @@ DevMemoryAlloc (BM_CONTEXT *pBMContext,
case hm_wrapped_virtaddr:
case hm_contiguous:
{
- psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap,
- pMapping->DevVAddr,
- SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
- pMapping->uSize,
- uFlags,
- (IMG_HANDLE)pMapping);
-
+ if (uFlags & PVRSRV_MEM_SPARSE)
+ {
+ /* Check if this device supports sparse mappings */
+ PVR_ASSERT(psDeviceNode->pfnMMUMapPagesSparse != IMG_NULL);
+ psDeviceNode->pfnMMUMapPagesSparse(pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+ pMapping->ui32ChunkSize,
+ pMapping->ui32NumVirtChunks,
+ pMapping->ui32NumPhysChunks,
+ pMapping->pabMapChunk,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
+ else
+ {
+ psDeviceNode->pfnMMUMapPages ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ SysCpuPAddrToSysPAddr (pMapping->CpuPAddr),
+ pMapping->uSize,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
*pDevVAddr = pMapping->DevVAddr;
break;
}
case hm_env:
{
- psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
- pMapping->DevVAddr,
- pMapping->uSize,
- pMapping->CpuVAddr,
- pMapping->hOSMemHandle,
- pDevVAddr,
- uFlags,
- (IMG_HANDLE)pMapping);
+ if (uFlags & PVRSRV_MEM_SPARSE)
+ {
+ /* Check if this device supports sparse mappings */
+ PVR_ASSERT(psDeviceNode->pfnMMUMapShadowSparse != IMG_NULL);
+ psDeviceNode->pfnMMUMapShadowSparse(pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->ui32ChunkSize,
+ pMapping->ui32NumVirtChunks,
+ pMapping->ui32NumPhysChunks,
+ pMapping->pabMapChunk,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
+ else
+ {
+ psDeviceNode->pfnMMUMapShadow ( pMapping->pBMHeap->pMMUHeap,
+ pMapping->DevVAddr,
+ pMapping->uSize,
+ pMapping->CpuVAddr,
+ pMapping->hOSMemHandle,
+ pDevVAddr,
+ uFlags,
+ (IMG_HANDLE)pMapping);
+ }
break;
}
case hm_wrapped_scatter:
@@ -1886,10 +2433,10 @@ DevMemoryFree (BM_MAPPING *pMapping)
if (sDevPAddr.uiAddr != 0)
{
#ifdef PDUMP
-
+ /* pdump the memory free */
if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
{
-
+ /* physical memory size differs in the case of Dummy allocations */
ui32PSize = pMapping->pBMHeap->sDevArena.ui32DataPageSize;
}
else
@@ -1902,286 +2449,170 @@ DevMemoryFree (BM_MAPPING *pMapping)
ui32PSize,
pMapping->pBMHeap->sDevArena.ui32DataPageSize,
(IMG_HANDLE)pMapping,
- (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE);
+ (pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) ? IMG_TRUE : IMG_FALSE,
+ (pMapping->ui32Flags & PVRSRV_MEM_SPARSE) ? IMG_TRUE : IMG_FALSE);
#endif
}
- psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSize));
+ PVR_ASSERT(pMapping->uSizeVM != 0);
+ psDeviceNode->pfnMMUFree (pMapping->pBMHeap->pMMUHeap, pMapping->DevVAddr, IMG_CAST_TO_DEVVADDR_UINT(pMapping->uSizeVM));
pMapping->bUnmapped = IMG_TRUE;
}
-static PXProcShareDataNode gXProcWorkaroundShareDataNode = NULL;
-
-static const char const* gcXprocId = "Xproc Shared Buffer";
-
-typedef struct XProcShareDataNode{
- const char* cXprocId;
- IMG_UINT32 ui32RefCount;
- IMG_UINT32 ui32AllocFlags;
- IMG_UINT32 ui32Size;
- IMG_UINT32 ui32PageSize;
- RA_ARENA *psArena;
- IMG_SYS_PHYADDR sSysPAddr;
- IMG_VOID *pvCpuVAddr;
- IMG_HANDLE hOSMemHandle;
- struct list_head list;
-}XProcShareDataNodeT;
-
-LIST_HEAD(gXProcShareList);
-
-static unsigned int gXProcShareCount = 0;
-
-static IMG_BOOL IsXprocShareObjectValid(PXProcShareDataNode pShareDataNode)
-{
- if(pShareDataNode->cXprocId == gcXprocId)
- return IMG_TRUE;
-
- PVR_DPF((PVR_DBG_ERROR, "Share Data Node Is Invalid!!!"));
- return IMG_FALSE;
-}
-
-static void XprocPrintListStats(void)
-{
- struct list_head *list_ptr;
- PXProcShareDataNode pShareDataNodeIt = NULL;
- unsigned used_objects = 0, unused_objects = 0, invalid_objects = 0;
-
- list_for_each(list_ptr, &gXProcShareList)
- {
- pShareDataNodeIt = list_entry(list_ptr, XProcShareDataNodeT, list);
- if(IMG_TRUE == IsXprocShareObjectValid(pShareDataNodeIt))
- {
- if ((pShareDataNodeIt->ui32RefCount > 0))
- {
- used_objects++;
- }
- else
- {
- unused_objects++;
- }
- }
- else
- {
- invalid_objects++;
- }
- }
- PVR_DPF((PVR_DBG_ERROR, "Share Data List stats: used %d, unused %d, invalid %d descriptors",
- used_objects, unused_objects, invalid_objects));
-}
-
-static PXProcShareDataNode XprocShareObjectCreate(void)
-{
- PXProcShareDataNode pShareDataNode = NULL;
-
- if (OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
- sizeof (XProcShareDataNodeT),
- (IMG_PVOID *)&pShareDataNode, IMG_NULL,
- /* "Xproc Shared Buffer" */ gcXprocId) != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "OSAllocMem: pShareDataNode alloc FAILED"));
- return NULL;
- }
-
- if(NULL == pShareDataNode)
- {
- PVR_DPF((PVR_DBG_ERROR, "XprocShareObjectCreate: pShareDataNode alloc FAILED"));
- return NULL;
- }
-
- OSMemSet(pShareDataNode, 0, sizeof (XProcShareDataNodeT));
-
- /* Make it valid */
- INIT_LIST_HEAD(&pShareDataNode->list);
- pShareDataNode->cXprocId = gcXprocId;
-
- /* Add it to the list */
- list_add(&pShareDataNode->list, &gXProcShareList);
- gXProcShareCount++;
-
- PVR_DPF ((PVR_DBG_MESSAGE, "Share Object %p created, ref count: %d", pShareDataNode, gXProcShareCount));
+/* If this array grows larger, it might be preferable to use a hashtable rather than an array. */
+#ifndef XPROC_WORKAROUND_NUM_SHAREABLES
+#define XPROC_WORKAROUND_NUM_SHAREABLES 200
+#endif
- if(gXProcShareCount > 5000)
- {
- PVR_DPF((PVR_DBG_ERROR, "Too Many Share Data Nodes %d. Potential memory leak!!!", gXProcShareCount));
- XprocPrintListStats();
- }
+#define XPROC_WORKAROUND_BAD_SHAREINDEX 0773407734
- return pShareDataNode;
-}
+#define XPROC_WORKAROUND_UNKNOWN 0
+#define XPROC_WORKAROUND_ALLOC 1
+#define XPROC_WORKAROUND_MAP 2
-static void XprocShareObjectDestroy(PXProcShareDataNode pShareDataNode)
-{
- list_del(&pShareDataNode->list);
- pShareDataNode->hOSMemHandle = NULL;
- pShareDataNode->cXprocId = NULL;
- OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof (XProcShareDataNodeT), pShareDataNode, IMG_NULL);
- if(gXProcWorkaroundShareDataNode == pShareDataNode)
- {
- PVR_DPF((PVR_DBG_ERROR, "Share Data Node %p destroyed. Ignore the following error message about it!!!", pShareDataNode));
- gXProcWorkaroundShareDataNode = NULL;
- }
- gXProcShareCount--;
+static IMG_UINT32 gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+static IMG_UINT32 gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
- PVR_DPF ((PVR_DBG_MESSAGE, "Share Object %p destoyed, ref count: %d", pShareDataNode, gXProcShareCount));
-}
+/* PRQA S 0686 10 */ /* force compiler to init structure */
+XPROC_DATA gXProcWorkaroundShareData[XPROC_WORKAROUND_NUM_SHAREABLES] = {{0}};
-PVRSRV_ERROR BM_XProcSetShareIndex(PXProcShareDataNode pShareDataNode)
+PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index)
{
-
- if (gXProcWorkaroundShareDataNode != NULL)
+ /* if you fail this assertion - did you acquire the mutex?
+ did you call "set" exactly once?
+ did you call "unset" exactly once per set?
+ */
+ if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
{
- PVR_DPF((PVR_DBG_ERROR, "Share Data Node already set!"));
- return PVRSRV_ERROR_NOT_OWNER;
- }
-
- if(pShareDataNode == NULL)
- {
- PVR_DPF((PVR_DBG_ERROR, "Trying to set NULL pShareDataNode!"));
+ PVR_DPF((PVR_DBG_ERROR, "No, it's already set!"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
- if(IMG_TRUE != IsXprocShareObjectValid(pShareDataNode))
- return PVRSRV_ERROR_INVALID_PARAMS;
-
- gXProcWorkaroundShareDataNode = pShareDataNode;
+ gXProcWorkaroundShareIndex = ui32Index;
+ gXProcWorkaroundState = XPROC_WORKAROUND_MAP;
return PVRSRV_OK;
}
-PVRSRV_ERROR BM_XProcFinishShareIndex(PXProcShareDataNode pShareDataNode, IMG_BOOL freeIfNotUsed)
+PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index)
{
- if (gXProcWorkaroundShareDataNode == NULL)
+ /* if you fail this assertion - did you acquire the mutex?
+ did you call "set" exactly once?
+ did you call "unset" exactly once per set?
+ */
+ if (gXProcWorkaroundShareIndex == XPROC_WORKAROUND_BAD_SHAREINDEX)
{
- PVR_DPF((PVR_DBG_ERROR, "Share Data Node is NULL and should of been %p", pShareDataNode));
+ PVR_DPF((PVR_DBG_ERROR, "huh? how can it be bad??"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
- if (gXProcWorkaroundShareDataNode != pShareDataNode)
+ if (gXProcWorkaroundShareIndex != ui32Index)
{
- PVR_DPF((PVR_DBG_ERROR, "gXProcWorkaroundShareDataNode == %p != %p == pShareDataNode", gXProcWorkaroundShareDataNode, pShareDataNode));
+ PVR_DPF((PVR_DBG_ERROR, "gXProcWorkaroundShareIndex == 0x%08x != 0x%08x == ui32Index", gXProcWorkaroundShareIndex, ui32Index));
return PVRSRV_ERROR_INVALID_PARAMS;
}
- if (pShareDataNode == NULL)
- {
- PVR_DPF((PVR_DBG_ERROR, "pShareDataNode == NULL"));
- return PVRSRV_ERROR_INVALID_PARAMS;
- }
-
- if((freeIfNotUsed == IMG_TRUE) &&
- (IMG_TRUE == IsXprocShareObjectValid(pShareDataNode)) &&
- (pShareDataNode->ui32RefCount == 0x00))
- {
- PVR_DPF((PVR_DBG_ERROR, "Explicit free of pShareDataNode"));
- XprocShareObjectDestroy(pShareDataNode);
- }
-
- gXProcWorkaroundShareDataNode = NULL;
-
- PVR_DPF ((PVR_DBG_MESSAGE, "BM_XProcFinishShareIndex for %p", pShareDataNode));
+ gXProcWorkaroundShareIndex = XPROC_WORKAROUND_BAD_SHAREINDEX;
+ gXProcWorkaroundState = XPROC_WORKAROUND_UNKNOWN;
return PVRSRV_OK;
}
-PXProcShareDataNode BM_XProcAllocNewBuffer(void)
+PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index)
{
- PXProcShareDataNode pShareDataNode;
-
- if (gXProcWorkaroundShareDataNode != NULL)
+ /* if you fail this assertion - did you acquire the mutex?
+ did you call "set" exactly once?
+ did you call "unset" exactly once per set?
+ */
+ if (gXProcWorkaroundShareIndex != XPROC_WORKAROUND_BAD_SHAREINDEX)
{
- PVR_DPF((PVR_DBG_ERROR, "Share Data Node already allocated/set!"));
- return NULL;
+ return PVRSRV_ERROR_INVALID_PARAMS;
}
- pShareDataNode = XprocShareObjectCreate();
- if(NULL == pShareDataNode)
- return NULL;
-
- PVR_DPF ((PVR_DBG_MESSAGE, "BM_XProcAllocNewBuffer and SET %p", pShareDataNode));
-
- gXProcWorkaroundShareDataNode = pShareDataNode;
-
- return pShareDataNode;
-}
+ for (*pui32Index = 0; *pui32Index < XPROC_WORKAROUND_NUM_SHAREABLES; (*pui32Index)++)
+ {
+ if (gXProcWorkaroundShareData[*pui32Index].ui32RefCount == 0)
+ {
+ gXProcWorkaroundShareIndex = *pui32Index;
+ gXProcWorkaroundState = XPROC_WORKAROUND_ALLOC;
+ return PVRSRV_OK;
+ }
+ }
-IMG_UINT32 BM_XProcWorkaroundGetRefCount(IMG_UINT32 ui32Index)
-{
- return gXProcWorkaroundShareDataNode->ui32RefCount;
+ PVR_DPF((PVR_DBG_ERROR, "ran out of shared buffers"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
}
static PVRSRV_ERROR
-XProcAllocShareable(RA_ARENA *psArena,
+XProcWorkaroundAllocShareable(RA_ARENA *psArena,
IMG_UINT32 ui32AllocFlags,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_VOID **ppvCpuVAddr,
IMG_HANDLE *phOSMemHandle)
{
if ((ui32AllocFlags & PVRSRV_MEM_XPROC) == 0)
{
- PVR_DPF((PVR_DBG_ERROR, "XProcAllocShareable: bad flags"));
+ PVR_DPF((PVR_DBG_VERBOSE, "XProcWorkaroundAllocShareable: bad flags"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
- if (gXProcWorkaroundShareDataNode == NULL)
- {
- PVR_DPF((PVR_DBG_ERROR, "XProcAllocShareable: gXProcWorkaroundShareDataNode == NULL"));
- return PVRSRV_ERROR_NOT_OWNER;
- }
-
- if(IMG_TRUE != IsXprocShareObjectValid(gXProcWorkaroundShareDataNode))
- return PVRSRV_ERROR_INVALID_PARAMS;
-
- if (gXProcWorkaroundShareDataNode->ui32RefCount > 0)
+ if (gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32RefCount > 0)
{
PVR_DPF((PVR_DBG_VERBOSE,
- "XProcAllocShareable: re-using previously allocated pages %p", gXProcWorkaroundShareDataNode));
+ "XProcWorkaroundAllocShareable: re-using previously allocated pages"));
ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
- if (ui32AllocFlags != gXProcWorkaroundShareDataNode->ui32AllocFlags)
+ if (ui32AllocFlags != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags)
{
PVR_DPF((PVR_DBG_ERROR,
- "Bucket Flags don't match! (bucket had 0x%08x, new one 0x%08x)",
- gXProcWorkaroundShareDataNode->ui32AllocFlags,
+ "Can't! Flags don't match! (I had 0x%08x, you gave 0x%08x)",
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags,
ui32AllocFlags));
return PVRSRV_ERROR_INVALID_PARAMS;
}
- if (ui32Size != gXProcWorkaroundShareDataNode->ui32Size)
+ if (ui32Size != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size)
{
PVR_DPF((PVR_DBG_ERROR,
- "Bucket Size doesn't match! (bucket size %d, new size %d )",
- gXProcWorkaroundShareDataNode->ui32Size, ui32Size));
+ "Can't! Size doesn't match!"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
- if (ui32PageSize != gXProcWorkaroundShareDataNode->ui32PageSize)
+ if (ui32PageSize != gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize)
{
PVR_DPF((PVR_DBG_ERROR,
- "Bucket Page Size doesn't match!(bucket size %d, new size %d )",
- gXProcWorkaroundShareDataNode->ui32PageSize, ui32PageSize));
+ "Can't! Page Size doesn't match!"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
- *ppvCpuVAddr = gXProcWorkaroundShareDataNode->pvCpuVAddr;
- *phOSMemHandle = gXProcWorkaroundShareDataNode->hOSMemHandle;
+ *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
+ *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
- gXProcWorkaroundShareDataNode->ui32RefCount++;
+ BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
return PVRSRV_OK;
}
else
{
+ if (gXProcWorkaroundState != XPROC_WORKAROUND_ALLOC)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "XPROC workaround in bad state! About to allocate memory from non-alloc state! (%d)",
+ gXProcWorkaroundState));
+ }
+ PVR_ASSERT(gXProcWorkaroundState == XPROC_WORKAROUND_ALLOC);
+
if (psArena != IMG_NULL)
{
IMG_CPU_PHYADDR sCpuPAddr;
IMG_SYS_PHYADDR sSysPAddr;
PVR_DPF((PVR_DBG_VERBOSE,
- "XProcAllocShareable: making a NEW allocation from local mem %p(%d)",
- gXProcWorkaroundShareDataNode, gXProcWorkaroundShareDataNode->ui32RefCount));
+ "XProcWorkaroundAllocShareable: making a NEW allocation from local mem"));
if (!RA_Alloc (psArena,
ui32Size,
@@ -2190,9 +2621,11 @@ XProcAllocShareable(RA_ARENA *psArena,
0,
ui32PageSize,
0,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
{
- PVR_DPF((PVR_DBG_ERROR, "XProcAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size));
+ PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: RA_Alloc(0x%x) FAILED", ui32Size));
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
@@ -2200,127 +2633,194 @@ XProcAllocShareable(RA_ARENA *psArena,
if(OSReservePhys(sCpuPAddr,
ui32Size,
ui32AllocFlags,
- (IMG_VOID **)&gXProcWorkaroundShareDataNode->pvCpuVAddr,
- &gXProcWorkaroundShareDataNode->hOSMemHandle) != PVRSRV_OK)
+ IMG_NULL,
+ (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
+ &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "XProcAllocShareable: OSReservePhys failed"));
+ PVR_DPF((PVR_DBG_ERROR, "XProcWorkaroundAllocShareable: OSReservePhys failed"));
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
- gXProcWorkaroundShareDataNode->sSysPAddr = sSysPAddr;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].sSysPAddr = sSysPAddr;
}
else
{
- PVR_DPF((PVR_DBG_VERBOSE,
- "XProcAllocShareable: making a NEW allocation from OS %p(%d)",
- gXProcWorkaroundShareDataNode, gXProcWorkaroundShareDataNode->ui32RefCount));
+ PVR_DPF((PVR_DBG_VERBOSE,
+ "XProcWorkaroundAllocShareable: making a NEW allocation from OS"));
ui32AllocFlags &= ~PVRSRV_HAP_MAPTYPE_MASK;
ui32AllocFlags |= PVRSRV_HAP_SINGLE_PROCESS;
-
+ /* allocate pages from the OS RAM */
if (OSAllocPages(ui32AllocFlags,
ui32Size,
ui32PageSize,
- (IMG_VOID **)&gXProcWorkaroundShareDataNode->pvCpuVAddr,
- &gXProcWorkaroundShareDataNode->hOSMemHandle) != PVRSRV_OK)
+ pvPrivData,
+ ui32PrivDataLength,
+ IMG_NULL, /* FIXME: to support cross process sparse allocations */
+ (IMG_VOID **)&gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr,
+ &gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,
- "XProcAllocShareable: OSAllocPages(0x%x) failed",
+ "XProcWorkaroundAllocShareable: OSAllocPages(0x%x) failed",
ui32PageSize));
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
}
- gXProcWorkaroundShareDataNode->psArena = psArena;
- gXProcWorkaroundShareDataNode->ui32AllocFlags = ui32AllocFlags;
- gXProcWorkaroundShareDataNode->ui32Size = ui32Size;
- gXProcWorkaroundShareDataNode->ui32PageSize = ui32PageSize;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].psArena = psArena;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32AllocFlags = ui32AllocFlags;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32Size = ui32Size;
+ gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].ui32PageSize = ui32PageSize;
- *ppvCpuVAddr = gXProcWorkaroundShareDataNode->pvCpuVAddr;
- *phOSMemHandle = gXProcWorkaroundShareDataNode->hOSMemHandle;
+ *ppvCpuVAddr = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].pvCpuVAddr;
+ *phOSMemHandle = gXProcWorkaroundShareData[gXProcWorkaroundShareIndex].hOSMemHandle;
- gXProcWorkaroundShareDataNode->ui32RefCount++;
+ BM_XProcIndexAcquire(gXProcWorkaroundShareIndex);
return PVRSRV_OK;
}
}
-static PXProcShareDataNode XProcHandleToSI(IMG_HANDLE hOSMemHandle)
+static PVRSRV_ERROR XProcWorkaroundHandleToSI(IMG_HANDLE hOSMemHandle, IMG_UINT32 *pui32SI)
{
-
- struct list_head *list_ptr;
- PXProcShareDataNode pShareDataNode = NULL;
+ IMG_UINT32 ui32SI;
+ IMG_BOOL bFound;
+ IMG_BOOL bErrorDups;
- if(hOSMemHandle == NULL)
- return NULL;
+ bFound = IMG_FALSE;
+ bErrorDups = IMG_FALSE;
- list_for_each(list_ptr, &gXProcShareList)
+ for (ui32SI = 0; ui32SI < XPROC_WORKAROUND_NUM_SHAREABLES; ui32SI++)
{
- pShareDataNode = list_entry(list_ptr, XProcShareDataNodeT, list);
- if(IMG_TRUE == IsXprocShareObjectValid(pShareDataNode))
+ if (gXProcWorkaroundShareData[ui32SI].ui32RefCount>0 && gXProcWorkaroundShareData[ui32SI].hOSMemHandle == hOSMemHandle)
{
- if ((pShareDataNode->ui32RefCount > 0) && (pShareDataNode->hOSMemHandle == hOSMemHandle))
+ if (bFound)
{
- return pShareDataNode;
+ bErrorDups = IMG_TRUE;
+ }
+ else
+ {
+ *pui32SI = ui32SI;
+ bFound = IMG_TRUE;
}
}
}
- return NULL;
-}
-
-static IMG_VOID XProcFreeShareable(IMG_HANDLE hOSMemHandle)
-{
- PXProcShareDataNode pShareDataNode;
- pShareDataNode = XProcHandleToSI(hOSMemHandle);
- if (pShareDataNode == NULL)
+ if (bErrorDups || !bFound)
{
- PVR_DPF((PVR_DBG_ERROR, "XProcHandleToSI bad handle %p", hOSMemHandle));
- return;
+ return PVRSRV_ERROR_BM_BAD_SHAREMEM_HANDLE;
}
- pShareDataNode->ui32RefCount--;
+ return PVRSRV_OK;
+}
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+ PVRSRVBMXProcIncRef2(pszFile, iLine, ui32Index);
+#else
+ PVRSRVBMXProcIncRef(ui32Index);
+#endif
+}
- PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of Node[%p] from %d to %d",
- pShareDataNode, pShareDataNode->ui32RefCount+1, pShareDataNode->ui32RefCount));
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+#else
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index)
+#endif
+{
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+ PVRSRVBMXProcDecRef2(pszFile, iLine, ui32Index);
+#else
+ PVRSRVBMXProcDecRef(ui32Index);
+#endif
- if (pShareDataNode->ui32RefCount == 0)
+ PVR_DPF((PVR_DBG_VERBOSE, "Reduced refcount of SI[%d] from %d to %d",
+ ui32Index, gXProcWorkaroundShareData[ui32Index].ui32RefCount+1, gXProcWorkaroundShareData[ui32Index].ui32RefCount));
+
+ if (gXProcWorkaroundShareData[ui32Index].ui32RefCount == 0)
{
- if (pShareDataNode->psArena != IMG_NULL)
+ if (gXProcWorkaroundShareData[ui32Index].psArena != IMG_NULL)
{
IMG_SYS_PHYADDR sSysPAddr;
- if (pShareDataNode->pvCpuVAddr != IMG_NULL)
+ if (gXProcWorkaroundShareData[ui32Index].pvCpuVAddr != IMG_NULL)
{
- OSUnReservePhys(pShareDataNode->pvCpuVAddr,
- pShareDataNode->ui32Size,
- pShareDataNode->ui32AllocFlags,
- pShareDataNode->hOSMemHandle);
+ OSUnReservePhys(gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+ gXProcWorkaroundShareData[ui32Index].ui32Size,
+ gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
}
- sSysPAddr = pShareDataNode->sSysPAddr;
- RA_Free (pShareDataNode->psArena,
+ sSysPAddr = gXProcWorkaroundShareData[ui32Index].sSysPAddr;
+ RA_Free (gXProcWorkaroundShareData[ui32Index].psArena,
sSysPAddr.uiAddr,
IMG_FALSE);
}
else
{
PVR_DPF((PVR_DBG_VERBOSE, "freeing OS memory"));
- OSFreePages(pShareDataNode->ui32AllocFlags,
- pShareDataNode->ui32PageSize,
- pShareDataNode->pvCpuVAddr,
- pShareDataNode->hOSMemHandle);
+ OSFreePages(gXProcWorkaroundShareData[ui32Index].ui32AllocFlags,
+ gXProcWorkaroundShareData[ui32Index].ui32PageSize,
+ gXProcWorkaroundShareData[ui32Index].pvCpuVAddr,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle);
}
- XprocShareObjectDestroy(pShareDataNode);
}
}
+static IMG_VOID XProcWorkaroundFreeShareable(IMG_HANDLE hOSMemHandle)
+{
+ IMG_UINT32 ui32SI = (IMG_UINT32)((IMG_UINTPTR_T)hOSMemHandle & 0xffffU);
+ PVRSRV_ERROR eError;
+ eError = XProcWorkaroundHandleToSI(hOSMemHandle, &ui32SI);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "bad handle"));
+ return;
+ }
+
+ BM_XProcIndexRelease(ui32SI);
+}
+
+
+/*!
+******************************************************************************
+
+ @Function BM_ImportMemory
+
+ @Description Provide a resource allocator with a source of pages of memory
+ from the Host OS's own allocation. Allocates a block of pages
+ larger than requested, allowing the resource allocator to
+ operate a small cache of pre allocated pages.
+
+ @Input pH - buffer manager handle, not the void type is dictated
+ by the generic nature of the resource allocator interface.
+ @Input uRequestSize - requested size in bytes
+ @Output pActualSize - receives the actual size allocated in bytes
+ which may be >= requested size
+ @Output ppsMapping - receives the arbitrary user reference
+ associated with the underlying storage.
+ @Input uFlags - bit mask of allocation flags
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+ @Output pBase - receives a pointer to the allocated storage.
+
+ @Return IMG_TRUE - success
+ IMG_FALSE - failed
+
+ *****************************************************************************/
static IMG_BOOL
BM_ImportMemory (IMG_VOID *pH,
IMG_SIZE_T uRequestSize,
IMG_SIZE_T *pActualSize,
BM_MAPPING **ppsMapping,
IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase)
{
BM_MAPPING *pMapping;
@@ -2329,7 +2829,7 @@ BM_ImportMemory (IMG_VOID *pH,
IMG_BOOL bResult;
IMG_SIZE_T uSize;
IMG_SIZE_T uPSize;
- IMG_SIZE_T uDevVAddrAlignment = 0;
+ IMG_SIZE_T uDevVAddrAlignment = 0; /* ? */
PVR_DPF ((PVR_DBG_MESSAGE,
"BM_ImportMemory (pBMContext=0x%x, uRequestSize=0x%x, uFlags=0x%x, uAlign=0x%x)",
@@ -2361,16 +2861,25 @@ BM_ImportMemory (IMG_VOID *pH,
pMapping->DevVAddr.uiAddr = 0;
pMapping->CpuPAddr.uiAddr = 0;
pMapping->uSize = uSize;
+ if ((uFlags & PVRSRV_MEM_SPARSE) == 0)
+ {
+ pMapping->uSizeVM = uSize;
+ }
pMapping->pBMHeap = pBMHeap;
pMapping->ui32Flags = uFlags;
pMapping->bUnmapped = IMG_FALSE;
-
+
+ /*
+ * If anyone want's to know, pass back the actual size of our allocation.
+ * There could be up to an extra page's worth of memory which will be marked
+ * as free in the RA.
+ */
if (pActualSize)
{
*pActualSize = uSize;
}
-
+ /* if it's a dummy allocation only use one physical page */
if(pMapping->ui32Flags & PVRSRV_MEM_DUMMY)
{
uPSize = pBMHeap->sDevArena.ui32DataPageSize;
@@ -2385,13 +2894,15 @@ BM_ImportMemory (IMG_VOID *pH,
IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs | PVRSRV_MEM_XPROC;
IMG_BOOL bBadBackingStoreType;
- bBadBackingStoreType = IMG_TRUE;
+ if(uFlags & PVRSRV_MEM_ION)
+ {
+ ui32Attribs |= PVRSRV_MEM_ION;
+ }
+
+ bBadBackingStoreType = IMG_TRUE;
- if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0)
+ if ((ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG) != 0)
{
-#ifndef MAX
-#define MAX(a,b) ((a) > (b) ? (a) : (b))
-#endif
uDevVAddrAlignment = MAX(pBMHeap->sDevArena.ui32DataPageSize, HOST_PAGESIZE());
@@ -2400,70 +2911,81 @@ BM_ImportMemory (IMG_VOID *pH,
PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated"));
goto fail_mapping_alloc;
}
- uDevVAddrAlignment = 0;
+ uDevVAddrAlignment = 0; /* FIXME: find out why it doesn't work if alignment is specified */
-
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
}
-
- if (XProcAllocShareable(IMG_NULL,
- ui32Attribs,
- (IMG_UINT32)uPSize,
- pBMHeap->sDevArena.ui32DataPageSize,
- (IMG_VOID **)&pMapping->CpuVAddr,
- &pMapping->hOSMemHandle) != PVRSRV_OK)
+ /* allocate "shared" pages. */
+ if (XProcWorkaroundAllocShareable(IMG_NULL,
+ ui32Attribs,
+ (IMG_UINT32)uPSize,
+ pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ (IMG_VOID **)&pMapping->CpuVAddr,
+ &pMapping->hOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,
- "BM_ImportMemory: XProcAllocShareable(0x%x) failed", uPSize));
+ "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed",
+ uPSize));
goto fail_mapping_alloc;
}
-
-
-
+ /* specify how page addresses are derived */
+ /* it works just like "env" now - no need to record
+ it as shareable, as we use the actual hOSMemHandle
+ and only divert to our wrapper layer based on Attribs */
pMapping->eCpuMemoryOrigin = hm_env;
- bBadBackingStoreType = IMG_FALSE;
+ bBadBackingStoreType = IMG_FALSE;
}
- if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0)
+ if ((ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG) != 0)
{
- uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize;
+ uDevVAddrAlignment = pBMHeap->sDevArena.ui32DataPageSize;
if (uPSize % uDevVAddrAlignment != 0)
{
PVR_DPF((PVR_DBG_ERROR, "Cannot use use this memory sharing workaround with allocations that might be suballocated"));
goto fail_mapping_alloc;
}
- uDevVAddrAlignment = 0;
+ uDevVAddrAlignment = 0; /* FIXME: find out why it doesn't work if alignment is specified */
-
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
}
-
- if (XProcAllocShareable(pBMHeap->pLocalDevMemArena,
+ /* allocate "shared" pages. */
+ if (XProcWorkaroundAllocShareable(pBMHeap->pLocalDevMemArena,
ui32Attribs,
(IMG_UINT32)uPSize,
pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_VOID **)&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,
- "BM_ImportMemory: XProcAllocShareable(0x%x) failed",
+ "BM_ImportMemory: XProcWorkaroundAllocShareable(0x%x) failed",
uPSize));
goto fail_mapping_alloc;
}
-
-
-
+ /* specify how page addresses are derived */
+ /* it works just like "env" now - no need to record
+ it as shareable, as we use the actual hOSMemHandle
+ and only divert to our wrapper layer based on Attribs */
pMapping->eCpuMemoryOrigin = hm_env;
bBadBackingStoreType = IMG_FALSE;
}
@@ -2476,23 +2998,41 @@ BM_ImportMemory (IMG_VOID *pH,
}
else
-
-
+ /*
+ What type of backing store do we have?
+ */
if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
{
IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
-
+ /* The allocation code needs to know this is a sparse mapping */
+ if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ ui32Attribs |= PVRSRV_MEM_SPARSE;
+ }
+
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
ui32Attribs |= (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK);
}
-
+ if (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM)
+ {
+ ui32Attribs &= ~PVRSRV_MEM_ALLOCATENONCACHEDMEM;
+ ui32Attribs |= (pMapping->ui32Flags & PVRSRV_MEM_ALLOCATENONCACHEDMEM);
+ }
+
+ /* allocate pages from the OS RAM */
if (OSAllocPages(ui32Attribs,
uPSize,
pBMHeap->sDevArena.ui32DataPageSize,
+ pvPrivData,
+ ui32PrivDataLength,
+ pMapping,
(IMG_VOID **)&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
@@ -2502,7 +3042,7 @@ BM_ImportMemory (IMG_VOID *pH,
goto fail_mapping_alloc;
}
-
+ /* specify how page addresses are derived */
pMapping->eCpuMemoryOrigin = hm_env;
}
else if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG)
@@ -2510,10 +3050,18 @@ BM_ImportMemory (IMG_VOID *pH,
IMG_SYS_PHYADDR sSysPAddr;
IMG_UINT32 ui32Attribs = pBMHeap->ui32Attribs;
-
+ /* The allocation code needs to know this is a sparse mapping */
+ if (pMapping->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ ui32Attribs |= PVRSRV_MEM_SPARSE;
+ }
+
+ /* allocate pages from the local device memory allocator */
PVR_ASSERT(pBMHeap->pLocalDevMemArena != IMG_NULL);
-
+ /* If the user has specified heap CACHETYPE flags, use them to
+ * override the flags inherited from the heap.
+ */
if (pMapping->ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
ui32Attribs &= ~PVRSRV_HAP_CACHETYPE_MASK;
@@ -2527,17 +3075,20 @@ BM_ImportMemory (IMG_VOID *pH,
0,
pBMHeap->sDevArena.ui32DataPageSize,
0,
+ pvPrivData,
+ ui32PrivDataLength,
(IMG_UINTPTR_T *)&sSysPAddr.uiAddr))
{
PVR_DPF((PVR_DBG_ERROR, "BM_ImportMemory: RA_Alloc(0x%x) FAILED", uPSize));
goto fail_mapping_alloc;
}
-
+ /* derive the CPU virtual address */
pMapping->CpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
if(OSReservePhys(pMapping->CpuPAddr,
uPSize,
ui32Attribs,
+ pMapping,
&pMapping->CpuVAddr,
&pMapping->hOSMemHandle) != PVRSRV_OK)
{
@@ -2545,7 +3096,7 @@ BM_ImportMemory (IMG_VOID *pH,
goto fail_dev_mem_alloc;
}
-
+ /* specify how page addresses are derived */
pMapping->eCpuMemoryOrigin = hm_contiguous;
}
else
@@ -2554,26 +3105,32 @@ BM_ImportMemory (IMG_VOID *pH,
goto fail_mapping_alloc;
}
-
- bResult = DevMemoryAlloc (pBMContext,
- pMapping,
- IMG_NULL,
- uFlags,
- (IMG_UINT32)uDevVAddrAlignment,
- &pMapping->DevVAddr);
- if (!bResult)
+ /*
+ * Allocate some device memory for what we just allocated.
+ */
+ if ((uFlags & PVRSRV_MEM_SPARSE) == 0)
{
- PVR_DPF((PVR_DBG_ERROR,
- "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
- pMapping->uSize));
- goto fail_dev_mem_alloc;
- }
-
-
+ bResult = DevMemoryAlloc (pBMContext,
+ pMapping,
+ IMG_NULL,
+ uFlags,
+ (IMG_UINT32)uDevVAddrAlignment,
+ &pMapping->DevVAddr);
+ if (!bResult)
+ {
+ PVR_DPF((PVR_DBG_ERROR,
+ "BM_ImportMemory: DevMemoryAlloc(0x%x) failed",
+ pMapping->uSize));
+ goto fail_dev_mem_alloc;
+ }
- PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+ /* uDevVAddrAlignment is currently set to zero so QAC generates warning which we override */
+ /* PRQA S 3356,3358 1 */
+ PVR_ASSERT (uDevVAddrAlignment>1?(pMapping->DevVAddr.uiAddr%uDevVAddrAlignment)==0:1);
+ PVR_ASSERT(pBase);
+ *pBase = pMapping->DevVAddr.uiAddr;
+ }
- *pBase = pMapping->DevVAddr.uiAddr;
*ppsMapping = pMapping;
PVR_DPF ((PVR_DBG_MESSAGE, "BM_ImportMemory: IMG_TRUE"));
@@ -2582,7 +3139,7 @@ BM_ImportMemory (IMG_VOID *pH,
fail_dev_mem_alloc:
if (pMapping && (pMapping->CpuVAddr || pMapping->hOSMemHandle))
{
-
+ /* the size is double the actual size for interleaved allocations */
if(pMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED)
{
pMapping->uSize /= 2;
@@ -2599,7 +3156,7 @@ fail_dev_mem_alloc:
if (uFlags & PVRSRV_MEM_XPROC)
{
- XProcFreeShareable(pMapping->hOSMemHandle);
+ XProcWorkaroundFreeShareable(pMapping->hOSMemHandle);
}
else
if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
@@ -2626,12 +3183,28 @@ fail_dev_mem_alloc:
}
fail_mapping_alloc:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), pMapping, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_exit:
return IMG_FALSE;
}
+/*!
+******************************************************************************
+
+ @Function BM_FreeMemory
+
+ @Description Free a block of pages previously allocated via
+ BM_ImportMemory.
+
+ @Input h - buffer manager handle, not the void type as dictated by
+ the generic nature of the resource allocator interface.
+ @Input _base - base address of blocks to free.
+ @Input psMapping - arbitrary user reference associated with the
+ underlying storage provided by BM_ImportMemory
+ @Return None
+
+ *****************************************************************************/
static IMG_VOID
BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
{
@@ -2652,9 +3225,17 @@ BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
return;
}
- DevMemoryFree (psMapping);
+ /*
+ Only free the virtual memory if we got as far a allocating it.
+ This NULL check should be safe as we always have a guard page
+ at virtual address 0x00000000
+ */
+ if (psMapping->DevVAddr.uiAddr)
+ {
+ DevMemoryFree (psMapping);
+ }
-
+ /* the size is double the actual for interleaved */
if((psMapping->ui32Flags & PVRSRV_MEM_INTERLEAVED) != 0)
{
psMapping->uSize /= 2;
@@ -2671,7 +3252,7 @@ BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
if (psMapping->ui32Flags & PVRSRV_MEM_XPROC)
{
- XProcFreeShareable(psMapping->hOSMemHandle);
+ XProcWorkaroundFreeShareable(psMapping->hOSMemHandle);
}
else
if(pBMHeap->ui32Attribs & PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG)
@@ -2697,13 +3278,30 @@ BM_FreeMemory (IMG_VOID *h, IMG_UINTPTR_T _base, BM_MAPPING *psMapping)
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BM_MAPPING), psMapping, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
PVR_DPF((PVR_DBG_MESSAGE,
"..BM_FreeMemory (h=0x%x, base=0x%x)",
(IMG_UINTPTR_T)h, _base));
}
+/*!
+******************************************************************************
+
+ @Function BM_GetPhysPageAddr
+
+ @Description
+
+ @Input psMemInfo
+
+ @Input sDevVPageAddr
+
+ @Output psDevPAddr
+
+ @Return IMG_VOID
+
+******************************************************************************/
+
IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_DEV_VIRTADDR sDevVPageAddr,
IMG_DEV_PHYADDR *psDevPAddr)
@@ -2712,12 +3310,12 @@ IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
PVR_DPF((PVR_DBG_MESSAGE, "BM_GetPhysPageAddr"));
- PVR_ASSERT (psMemInfo && psDevPAddr)
+ PVR_ASSERT(psMemInfo && psDevPAddr);
-
+ /* check it's a page address */
PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
-
+ /* PRQA S 0505 4 */ /* PVR_ASSERT should catch NULL ptrs */
psDeviceNode = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pBMContext->psDeviceNode;
*psDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->pMMUHeap,
@@ -2725,6 +3323,16 @@ IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
}
+/*!
+******************************************************************************
+ @Function BM_GetMMUContext
+
+ @Description utility function to return the MMU context
+
+ @Input hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
{
BM_HEAP *pBMHeap = (BM_HEAP*)hDevMemHeap;
@@ -2734,6 +3342,16 @@ MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap)
return pBMHeap->pBMContext->psMMUContext;
}
+/*!
+******************************************************************************
+ @Function BM_GetMMUContextFromMemContext
+
+ @Description utility function to return the MMU context
+
+ @Input hDevMemContext - the Dev mem context handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
{
BM_CONTEXT *pBMContext = (BM_CONTEXT*)hDevMemContext;
@@ -2743,6 +3361,16 @@ MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext)
return pBMContext->psMMUContext;
}
+/*!
+******************************************************************************
+ @Function BM_GetMMUHeap
+
+ @Description utility function to return the MMU heap handle
+
+ @Input hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
{
PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMMUHeap"));
@@ -2751,6 +3379,16 @@ IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap)
}
+/*!
+******************************************************************************
+ @Function BM_GetDeviceNode
+
+ @Description utility function to return the devicenode from the BM Context
+
+ @Input hDevMemContext - the Dev Mem Context
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
{
PVR_DPF((PVR_DBG_VERBOSE, "BM_GetDeviceNode"));
@@ -2759,6 +3397,16 @@ PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext)
}
+/*!
+******************************************************************************
+ @Function BM_GetMappingHandle
+
+ @Description utility function to return the mapping handle from a meminfo
+
+ @Input psMemInfo - kernel meminfo
+
+ @Return mapping handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
PVR_DPF((PVR_DBG_VERBOSE, "BM_GetMappingHandle"));
@@ -2766,3 +3414,115 @@ IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
return ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->hOSMemHandle;
}
+/*!
+******************************************************************************
+ @Function BM_MappingHandleFromBuffer
+
+ @Description utility function to get the BM mapping handle from a BM buffer
+
+ @Input hBuffer - Handle to BM buffer
+
+ @Return BM mapping handle
+**************************************************************************/
+IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer)
+{
+ BM_BUF *psBuffer;
+
+ PVR_ASSERT(hBuffer != IMG_NULL);
+ psBuffer = hBuffer;
+ return psBuffer->pMapping;
+}
+
+/*!
+******************************************************************************
+ @Function BM_GetVirtualSize
+
+ @Description utility function to get the VM size of a BM mapping
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Return VM size of mapping
+**************************************************************************/
+IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle)
+{
+ BM_MAPPING *psMapping;
+
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psMapping = hBMHandle;
+ return psMapping->ui32ChunkSize * psMapping->ui32NumVirtChunks;
+}
+
+/*!
+******************************************************************************
+ @Function BM_MapPageAtOffset
+
+ @Description utility function check if the specificed offset in a BM mapping
+ is a page that needs tp be mapped
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32Offset - Offset into allocation
+
+ @Return IMG_TRUE if the page should be mapped
+**************************************************************************/
+IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset)
+{
+ BM_MAPPING *psMapping;
+ IMG_UINT32 ui32ChunkIndex;
+
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psMapping = hBMHandle;
+
+ ui32ChunkIndex = ui32Offset / psMapping->ui32ChunkSize;
+ /* Check for overrun */
+ PVR_ASSERT(ui32ChunkIndex <= psMapping->ui32NumVirtChunks);
+ return psMapping->pabMapChunk[ui32ChunkIndex];
+}
+
+/*!
+******************************************************************************
+ @Function BM_VirtOffsetToPhyscial
+
+ @Description utility function find of physical offset of a sparse allocation
+ from it's virtual offset.
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32VirtOffset - Virtual offset into allocation
+
+ @Output pui32PhysOffset - Physical offset
+
+ @Return IMG_TRUE if the virtual offset is physically backed
+**************************************************************************/
+IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle,
+ IMG_UINT32 ui32VirtOffset,
+ IMG_UINT32 *pui32PhysOffset)
+{
+ BM_MAPPING *psMapping;
+ IMG_UINT32 ui32ChunkOffset;
+ IMG_UINT32 ui32PhysOffset = 0;
+ IMG_UINT32 i;
+
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psMapping = hBMHandle;
+
+ ui32ChunkOffset = ui32VirtOffset / psMapping->ui32ChunkSize;
+ if (!psMapping->pabMapChunk[ui32ChunkOffset])
+ {
+ return IMG_FALSE;
+ }
+
+ for (i=0;i<ui32ChunkOffset;i++)
+ {
+ if (psMapping->pabMapChunk[i])
+ {
+ ui32PhysOffset += psMapping->ui32ChunkSize;
+ }
+ }
+ *pui32PhysOffset = ui32PhysOffset;
+
+ return IMG_TRUE;
+}
+/******************************************************************************
+ End of file (buffer_manager.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/deviceclass.c b/sgx/services4/srvkm/common/deviceclass.c
index 3882fdf..9ec4570 100644
--- a/sgx/services4/srvkm/common/deviceclass.c
+++ b/sgx/services4/srvkm/common/deviceclass.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device class services functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Kernel services functions for device class devices
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "buffer_manager.h"
@@ -45,17 +62,26 @@ void OSVSyncMISR(IMG_HANDLE, IMG_BOOL);
IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
IMG_BOOL bScheduleMISR);
#endif
+/***********************************************************************
+ Local Display Class Structures
+************************************************************************/
typedef struct PVRSRV_DC_SRV2DISP_KMJTABLE_TAG *PPVRSRV_DC_SRV2DISP_KMJTABLE;
+/*
+ Display Class Buffer Info
+*/
typedef struct PVRSRV_DC_BUFFER_TAG
{
-
+ /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
} PVRSRV_DC_BUFFER;
+/*
+ Display Device Class kernel swapchain information structure
+*/
typedef struct PVRSRV_DC_SWAPCHAIN_TAG
{
IMG_HANDLE hExtSwapChain;
@@ -68,11 +94,18 @@ typedef struct PVRSRV_DC_SWAPCHAIN_TAG
PVRSRV_DC_BUFFER *psLastFlipBuffer;
IMG_UINT32 ui32MinSwapInterval;
IMG_UINT32 ui32MaxSwapInterval;
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ PVRSRV_KERNEL_SYNC_INFO **ppsLastSyncInfos;
+ IMG_UINT32 ui32LastNumSyncInfos;
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
struct PVRSRV_DISPLAYCLASS_INFO_TAG *psDCInfo;
struct PVRSRV_DC_SWAPCHAIN_TAG *psNext;
} PVRSRV_DC_SWAPCHAIN;
+/*
+ Display Device Class kernel swapchain referecne structure
+*/
typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
{
struct PVRSRV_DC_SWAPCHAIN_TAG *psSwapChain;
@@ -80,6 +113,9 @@ typedef struct PVRSRV_DC_SWAPCHAIN_REF_TAG
} PVRSRV_DC_SWAPCHAIN_REF;
+/*
+ Display Device Class kernel services information structure
+*/
typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
{
IMG_UINT32 ui32RefCount;
@@ -92,6 +128,9 @@ typedef struct PVRSRV_DISPLAYCLASS_INFO_TAG
} PVRSRV_DISPLAYCLASS_INFO;
+/*
+ Per-context Display Device Class kernel services information structure
+*/
typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
@@ -99,17 +138,26 @@ typedef struct PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO_TAG
} PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO;
+/***********************************************************************
+ Local Buffer Class Structures
+************************************************************************/
typedef struct PVRSRV_BC_SRV2BUFFER_KMJTABLE_TAG *PPVRSRV_BC_SRV2BUFFER_KMJTABLE;
+/*
+ Buffer Class Buffer Info
+*/
typedef struct PVRSRV_BC_BUFFER_TAG
{
-
+ /* BC/DC common details - THIS MUST BE THE FIRST MEMBER */
PVRSRV_DEVICECLASS_BUFFER sDeviceClassBuffer;
struct PVRSRV_BUFFERCLASS_INFO_TAG *psBCInfo;
} PVRSRV_BC_BUFFER;
+/*
+ Buffer Device Class kernel services information structure
+*/
typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
{
IMG_UINT32 ui32RefCount;
@@ -117,13 +165,16 @@ typedef struct PVRSRV_BUFFERCLASS_INFO_TAG
IMG_HANDLE hExtDevice;
PPVRSRV_BC_SRV2BUFFER_KMJTABLE psFuncTable;
IMG_HANDLE hDevMemContext;
-
+ /* buffer info returned from 3rd party driver */
IMG_UINT32 ui32BufferCount;
PVRSRV_BC_BUFFER *psBuffer;
} PVRSRV_BUFFERCLASS_INFO;
+/*
+ Per-context Buffer Device Class kernel services information structure
+*/
typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
{
PVRSRV_BUFFERCLASS_INFO *psBCInfo;
@@ -131,6 +182,21 @@ typedef struct PVRSRV_BUFFERCLASS_PERCONTEXT_INFO_TAG
} PVRSRV_BUFFERCLASS_PERCONTEXT_INFO;
+/*!
+******************************************************************************
+ @Function DCDeviceHandleToDCInfo
+
+ @Description
+
+ Convert a client-visible 3rd party device class handle to an internal
+ PVRSRV_DISPLAYCLASS_INFO pointer.
+
+ @Input hDeviceKM - handle to display class device, returned from OpenDCDevice
+
+ @Return
+ success: pointer to PVRSRV_DISPLAYCLASS_INFO
+ failure: IMG_NULL
+******************************************************************************/
static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
{
PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
@@ -141,6 +207,21 @@ static PVRSRV_DISPLAYCLASS_INFO* DCDeviceHandleToDCInfo (IMG_HANDLE hDeviceKM)
}
+/*!
+******************************************************************************
+ @Function BCDeviceHandleToBCInfo
+
+ @Description
+
+ Convert a client-visible 3rd party buffer class handle to an internal
+ PVRSRV_BUFFERCLASS_INFO pointer.
+
+ @Input hDeviceKM - handle to buffer class device, returned from OpenBCDevice
+
+ @Return
+ success: pointer to PVRSRV_BUFFERCLASS_INFO
+ failure: IMG_NULL
+******************************************************************************/
static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
{
PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
@@ -150,6 +231,20 @@ static PVRSRV_BUFFERCLASS_INFO* BCDeviceHandleToBCInfo (IMG_HANDLE hDeviceKM)
return psBCPerContextInfo->psBCInfo;
}
+/*!
+******************************************************************************
+ @Function PVRSRVEnumerateDCKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode - The device node to be enumerated
+ va - variable arguments list, with:
+ pui32DevCount - The device count pointer (to be increased)
+ ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
+ peDeviceClass - The pointer to the device class of the psDeviceNode's to be enumerated.
+******************************************************************************/
static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
IMG_UINT *pui32DevCount;
@@ -172,18 +267,40 @@ static IMG_VOID PVRSRVEnumerateDCKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumerateDCKM
+
+ @Description
+
+ Enumerates devices available in a given class.
+ On first call, pass valid ptr for pui32DevCount and IMG_NULL for pui32DevID,
+ On second call, pass same ptr for pui32DevCount and client allocated ptr
+ for pui32DevID device id list
+
+ @Input hServices - handle for services connection
+ @Input ui32DevClass - device class identifier
+ @Output pui32DevCount - number of devices available in class
+ @Output pui32DevID - list of device ids in the device class
+
+ @Return
+ success: handle to matching display class device
+ failure: IMG_NULL
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
IMG_UINT32 *pui32DevCount,
IMG_UINT32 *pui32DevID )
{
-
+ /*PVRSRV_DEVICE_NODE *psDeviceNode;*/
IMG_UINT ui32DevCount = 0;
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
-
+ /* search devonode list for devices in specified class and return the device ids */
List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
&PVRSRVEnumerateDCKM_ForEachVaCb,
&ui32DevCount,
@@ -204,35 +321,55 @@ PVRSRV_ERROR PVRSRVEnumerateDCKM (PVRSRV_DEVICE_CLASS DeviceClass,
}
-static
-PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
- IMG_UINT32 *pui32DeviceID)
-{
- PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
- PVRSRV_DEVICE_NODE *psDeviceNode;
- SYS_DATA *psSysData;
-
-
-
-
+/*!
+******************************************************************************
+ @Function PVRSRVRegisterDCDeviceKM
+ @Description
+ registers an external device with the system
+ @Input psFuncTable : device function table
+ @Output pui32DeviceID : unique device key (for case of multiple identical devices)
+ @Return PVRSRV_ERROR :
+******************************************************************************/
+static
+PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
+ IMG_UINT32 *pui32DeviceID)
+{
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo = IMG_NULL;
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ SYS_DATA *psSysData;
+ /*
+ IN:
+ - name of client side ext. device driver library for subsequent loading
+ - predefined list of callbacks into kernel ext. device driver (based on class type)
+ FUNCTION TASKS:
+ - allocate display device class info structure
+ - hang ext.device kernel callbacks on this structure (pfnKSwapToSystem)
+ OUT:
+ - DEVICE_ID
+ - pass back devinfo? no
+ Q&A:
+ - DEVICE_ID passed in or allocated - assume allocate
+ */
SysAcquireData(&psSysData);
-
-
+ /*
+ If we got this far we're doing dynamic enumeration
+ or first time static registration
+ */
-
+ /* Allocate device control block */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psDCInfo),
(IMG_VOID **)&psDCInfo, IMG_NULL,
@@ -243,7 +380,7 @@ PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
}
OSMemSet (psDCInfo, 0, sizeof(*psDCInfo));
-
+ /* setup the display device information structure */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE),
(IMG_VOID **)&psDCInfo->psFuncTable, IMG_NULL,
@@ -254,10 +391,10 @@ PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
}
OSMemSet (psDCInfo->psFuncTable, 0, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE));
-
+ /* copy the jump table */
*psDCInfo->psFuncTable = *psFuncTable;
-
+ /* Allocate device node */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE),
(IMG_VOID **)&psDeviceNode, IMG_NULL,
@@ -275,7 +412,7 @@ PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_DISPLAY;
psDeviceNode->psSysData = psSysData;
-
+ /* allocate a unique device id */
if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVRegisterDCDeviceKM: "\
@@ -288,10 +425,10 @@ PVRSRV_ERROR PVRSRVRegisterDCDeviceKM (PVRSRV_DC_SRV2DISP_KMJTABLE *psFuncTable,
*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
}
-
+ /* Register the device with the system */
SysRegisterExternalDevice(psDeviceNode);
-
+ /* and finally insert the device into the dev-list */
List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
return PVRSRV_OK;
@@ -305,11 +442,25 @@ ErrorExit:
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemoveDCDeviceKM
+
+ @Description
+
+ Removes external device from services system record
+
+ @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
{
SYS_DATA *psSysData;
@@ -318,7 +469,7 @@ static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
SysAcquireData(&psSysData);
-
+ /*search the node matching the devindex and display class*/
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
@@ -327,37 +478,40 @@ static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
PVRSRV_DEVICE_CLASS_DISPLAY);
if (!psDeviceNode)
{
-
+ /*device not found*/
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRemoveDCDeviceKM: requested device %d not present", ui32DevIndex));
return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
}
-
+ /* setup DCInfo ptr */
psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
-
-
-
+ /*
+ The device can only be removed if there are
+ no open connections in the Services interface
+ */
if(psDCInfo->ui32RefCount == 0)
{
-
-
+ /*
+ Remove from the device list.
+ */
List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
-
+ /* Unregister the device with the system */
SysRemoveExternalDevice(psDeviceNode);
-
-
-
+ /*
+ OK found a device with a matching devindex
+ remove registration information
+ */
PVR_ASSERT(psDCInfo->ui32RefCount == 0);
(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SRV2DISP_KMJTABLE), psDCInfo->psFuncTable, IMG_NULL);
psDCInfo->psFuncTable = IMG_NULL;
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_INFO), psDCInfo, IMG_NULL);
-
+ /*not nulling original pointer, overwritten*/
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
else
{
@@ -369,6 +523,21 @@ static PVRSRV_ERROR PVRSRVRemoveDCDeviceKM(IMG_UINT32 ui32DevIndex)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterBCDeviceKM
+
+ @Description
+
+ registers an external device with the system
+
+ @Input psFuncTable : device function table
+ @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTable,
IMG_UINT32 *pui32DeviceID)
@@ -376,26 +545,30 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTabl
PVRSRV_BUFFERCLASS_INFO *psBCInfo = IMG_NULL;
PVRSRV_DEVICE_NODE *psDeviceNode;
SYS_DATA *psSysData;
-
-
-
-
-
-
-
-
-
-
+ /*
+ IN:
+ - name of client side ext. device driver library for subsequent loading
+ - predefined list of callbacks into kernel ext. device driver (based on class type)
+ FUNCTION TASKS:
+ - allocate buffer device class info structure
+ OUT:
+ - DEVICE_ID
+ - pass back devinfo? no
+ Q&A:
+ - DEVICE_ID passed in or allocated - assume allcoate
+ */
SysAcquireData(&psSysData);
-
-
+ /*
+ If we got this far we're doing dynamic enumeration
+ or first time static registration
+ */
-
+ /* Allocate device control block */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psBCInfo),
(IMG_VOID **)&psBCInfo, IMG_NULL,
@@ -406,7 +579,7 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTabl
}
OSMemSet (psBCInfo, 0, sizeof(*psBCInfo));
-
+ /* setup the buffer device information structure */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE),
(IMG_VOID **)&psBCInfo->psFuncTable, IMG_NULL,
@@ -417,10 +590,10 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTabl
}
OSMemSet (psBCInfo->psFuncTable, 0, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE));
-
+ /* copy the jump table */
*psBCInfo->psFuncTable = *psFuncTable;
-
+ /* Allocate device node */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE),
(IMG_VOID **)&psDeviceNode, IMG_NULL,
@@ -438,7 +611,7 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTabl
psDeviceNode->sDevId.eDeviceClass = PVRSRV_DEVICE_CLASS_BUFFER;
psDeviceNode->psSysData = psSysData;
-
+ /* allocate a unique device id */
if (AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterBCDeviceKM: Failed to allocate Device ID"));
@@ -450,7 +623,7 @@ PVRSRV_ERROR PVRSRVRegisterBCDeviceKM (PVRSRV_BC_SRV2BUFFER_KMJTABLE *psFuncTabl
*pui32DeviceID = psDeviceNode->sDevId.ui32DeviceIndex;
}
-
+ /* and finally insert the device into the dev-list */
List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
return PVRSRV_OK;
@@ -464,12 +637,26 @@ ErrorExit:
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
-
+ /*not nulling shared pointer, wasn't allocated to this point*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemoveBCDeviceKM
+
+ @Description
+
+ Removes external device from services system record
+
+ @Input ui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
{
SYS_DATA *psSysData;
@@ -478,7 +665,7 @@ static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
SysAcquireData(&psSysData);
-
+ /*search the device node with the devindex and buffer class*/
psDevNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
@@ -492,31 +679,33 @@ static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
}
-
-
+ /* set-up devnode ptr */
+/* psDevNode = *(ppsDevNode); */
+ /* setup BCInfo ptr */
psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDevNode->pvDevice;
-
-
-
+ /*
+ The device can only be removed if there are
+ no open connections in the Services interface
+ */
if(psBCInfo->ui32RefCount == 0)
{
-
-
+ /*
+ Remove from the device list.
+ */
List_PVRSRV_DEVICE_NODE_Remove(psDevNode);
-
-
-
+ /*
+ OK found a device with a matching devindex
+ remove registration information
+ */
(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
-
-
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_SRV2BUFFER_KMJTABLE), psBCInfo->psFuncTable, IMG_NULL);
psBCInfo->psFuncTable = IMG_NULL;
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_INFO), psBCInfo, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
(IMG_VOID)OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DEVICE_NODE), psDevNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
else
{
@@ -529,18 +718,29 @@ static PVRSRV_ERROR PVRSRVRemoveBCDeviceKM(IMG_UINT32 ui32DevIndex)
+/*!
+******************************************************************************
+
+ @Function PVRSRVCloseDCDeviceKM
+
+ @Description
+
+ Closes a connection to the Display Class device
+
+ @Input hDeviceKM : device handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM,
- IMG_BOOL bResManCallback)
+PVRSRV_ERROR PVRSRVCloseDCDeviceKM (IMG_HANDLE hDeviceKM)
{
PVRSRV_ERROR eError;
PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *psDCPerContextInfo;
- PVR_UNREFERENCED_PARAMETER(bResManCallback);
-
psDCPerContextInfo = (PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO *)hDeviceKM;
-
+ /* Remove the item from the resman list and trigger the callback. */
eError = ResManFreeResByPtr(psDCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
return eError;
@@ -562,38 +762,49 @@ static PVRSRV_ERROR CloseDCDeviceCallBack(IMG_PVOID pvParam,
if(psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount != 0)
{
- PVR_DPF((PVR_DBG_ERROR,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
+ PVR_DPF((PVR_DBG_MESSAGE,"CloseDCDeviceCallBack: system buffer (0x%p) still mapped (refcount = %d)",
&psDCInfo->sSystemBuffer.sDeviceClassBuffer,
psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount));
-
-#if 0
-
- return PVRSRV_ERROR_STILL_MAPPED;
-#endif
}
psDCInfo->ui32RefCount--;
if(psDCInfo->ui32RefCount == 0)
{
-
+ /* close the external device */
psDCInfo->psFuncTable->pfnCloseDCDevice(psDCInfo->hExtDevice);
- if (--psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
psDCInfo->hDevMemContext = IMG_NULL;
psDCInfo->hExtDevice = IMG_NULL;
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DISPLAYCLASS_PERCONTEXT_INFO), psDCPerContextInfo, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpenDCDeviceKM
+
+ @Description
+
+ Opens a connection to the Display Class device, associating the connection
+ with a Device Memory Context for a services managed device
+
+ @Input psPerProc : Per-process data
+ @Input ui32DeviceID : unique device index
+ @Input hDevCookie : devcookie used to derive the Device Memory
+ Context into BC surfaces will be mapped into
+ @Outut phDeviceKM : handle to the DC device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 ui32DeviceID,
@@ -614,7 +825,7 @@ PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
SysAcquireData(&psSysData);
-
+ /* find the matching devicenode */
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
@@ -628,9 +839,10 @@ PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
}
psDCInfo = (PVRSRV_DISPLAYCLASS_INFO*)psDeviceNode->pvDevice;
-
-
-
+ /*
+ Allocate the per-context DC Info before calling the external device,
+ to make error handling easier.
+ */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psDCPerContextInfo),
(IMG_VOID **)&psDCPerContextInfo, IMG_NULL,
@@ -646,10 +858,10 @@ PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
+ /* store the device kernel context to map into */
psDCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
-
+ /* create a syncinfo for the device's system surface */
eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
(IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext,
&psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
@@ -660,7 +872,7 @@ PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
return eError;
}
-
+ /* open the external device */
eError = psDCInfo->psFuncTable->pfnOpenDCDevice(ui32DeviceID,
&psDCInfo->hExtDevice,
(PVRSRV_SYNC_DATA*)psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM);
@@ -668,28 +880,55 @@ PVRSRV_ERROR PVRSRVOpenDCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to open external DC device"));
psDCInfo->ui32RefCount--;
- PVRSRVFreeSyncInfoKM(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo);
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
return eError;
}
- psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ eError = PVRSRVGetDCSystemBufferKM(psDCPerContextInfo, IMG_NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenDCDeviceKM: Failed to get system buffer"));
+ psDCInfo->ui32RefCount--;
+ PVRSRVKernelSyncInfoDecRef(psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
+ return eError;
+ }
psDCInfo->sSystemBuffer.sDeviceClassBuffer.ui32MemMapRefCount = 0;
}
+ else
+ {
+ psDCPerContextInfo->psDCInfo = psDCInfo;
+ }
- psDCPerContextInfo->psDCInfo = psDCInfo;
psDCPerContextInfo->hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DISPLAYCLASS_DEVICE,
psDCPerContextInfo,
0,
&CloseDCDeviceCallBack);
-
+ /* return a reference to the DCPerContextInfo */
*phDeviceKM = (IMG_HANDLE)psDCPerContextInfo;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumDCFormatsKM
+
+ @Description
+
+ Enumerates the devices pixel formats
+
+ @Input hDeviceKM : device handle
+ @Output pui32Count : number of pixel formats
+ @Output psFormat : format list
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
IMG_UINT32 *pui32Count,
@@ -705,12 +944,29 @@ PVRSRV_ERROR PVRSRVEnumDCFormatsKM (IMG_HANDLE hDeviceKM,
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
return psDCInfo->psFuncTable->pfnEnumDCFormats(psDCInfo->hExtDevice, pui32Count, psFormat);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumDCDimsKM
+
+ @Description
+
+ Enumerates the devices mode dimensions for a given pixel format
+
+ @Input hDeviceKM : device handle
+ @Input psFormat : pixel format
+ @Output pui32Count : number of dimensions
+ @Output psDim : dimensions list
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
DISPLAY_FORMAT *psFormat,
@@ -719,7 +975,7 @@ PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
- if(!hDeviceKM || !pui32Count || !psFormat)
+ if(!hDeviceKM || !pui32Count || !psFormat) // psDim==NULL to query number of dims
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVEnumDCDimsKM: Invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
@@ -727,11 +983,26 @@ PVRSRV_ERROR PVRSRVEnumDCDimsKM (IMG_HANDLE hDeviceKM,
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
return psDCInfo->psFuncTable->pfnEnumDCDims(psDCInfo->hExtDevice, psFormat, pui32Count, psDim);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDCSystemBufferKM
+
+ @Description
+
+ Get the primary surface and optionally return its buffer handle
+
+ @Input hDeviceKM : device handle
+ @Output phBuffer : Optional buffer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
IMG_HANDLE *phBuffer)
@@ -740,7 +1011,7 @@ PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
IMG_HANDLE hExtBuffer;
- if(!hDeviceKM || !phBuffer)
+ if(!hDeviceKM)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCSystemBufferKM: Invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
@@ -748,7 +1019,7 @@ PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
eError = psDCInfo->psFuncTable->pfnGetDCSystemBuffer(psDCInfo->hExtDevice, &hExtBuffer);
if(eError != PVRSRV_OK)
{
@@ -756,7 +1027,7 @@ PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
return eError;
}
-
+ /* save the new info */
psDCInfo->sSystemBuffer.sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
psDCInfo->sSystemBuffer.sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
@@ -764,13 +1035,30 @@ PVRSRV_ERROR PVRSRVGetDCSystemBufferKM (IMG_HANDLE hDeviceKM,
psDCInfo->sSystemBuffer.psDCInfo = psDCInfo;
-
- *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+ /* return handle */
+ if (phBuffer)
+ {
+ *phBuffer = (IMG_HANDLE)&(psDCInfo->sSystemBuffer);
+ }
return PVRSRV_OK;
}
+/******************************************************************************
+
+ @Function PVRSRVGetDCInfoKM
+
+ @Description
+
+ Gets Display Class device Info
+
+ @Input hDeviceKM : device handle
+ @Output psDisplayInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
DISPLAY_INFO *psDisplayInfo)
@@ -786,7 +1074,7 @@ PVRSRV_ERROR PVRSRVGetDCInfoKM (IMG_HANDLE hDeviceKM,
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* call into the display device driver to get info */
eError = psDCInfo->psFuncTable->pfnGetDCInfo(psDCInfo->hExtDevice, psDisplayInfo);
if (eError != PVRSRV_OK)
{
@@ -828,7 +1116,7 @@ static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
PVRSRV_DISPLAYCLASS_INFO *psDCInfo = psSwapChain->psDCInfo;
IMG_UINT32 i;
-
+ /* Update shared swapchains list */
if( psDCInfo->psDCSwapChainShared )
{
if( psDCInfo->psDCSwapChainShared == psSwapChain )
@@ -852,10 +1140,10 @@ static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
}
}
-
+ /* Destroy command queue before swapchain - it may use the swapchain when commands are flushed. */
PVRSRVDestroyCommandQueueKM(psSwapChain->psQueue);
-
+ /* call into the display device driver to destroy a swapchain */
eError = psDCInfo->psFuncTable->pfnDestroyDCSwapChain(psDCInfo->hExtDevice,
psSwapChain->hExtSwapChain);
@@ -865,20 +1153,25 @@ static PVRSRV_ERROR DestroyDCSwapChain(PVRSRV_DC_SWAPCHAIN *psSwapChain)
return eError;
}
-
+ /* free the resources */
for(i=0; i<psSwapChain->ui32BufferCount; i++)
{
if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ if (psSwapChain->ppsLastSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+ psSwapChain->ppsLastSyncInfos, IMG_NULL);
+ }
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return eError;
}
@@ -902,10 +1195,6 @@ static PVRSRV_ERROR DestroyDCSwapChainRefCallBack(IMG_PVOID pvParam,
PVR_DPF((PVR_DBG_ERROR, "DestroyDCSwapChainRefCallBack: swapchain (0x%p) still mapped (ui32MemMapRefCount = %d)",
&psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer,
psSwapChainRef->psSwapChain->asBuffer[i].sDeviceClassBuffer.ui32MemMapRefCount));
-#if 0
-
- return PVRSRV_ERROR_STILL_MAPPED;
-#endif
}
}
@@ -939,7 +1228,7 @@ static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerP
{
PVRSRV_DC_SWAPCHAIN_REF *psSwapChainRef = IMG_NULL;
-
+ /* Allocate swapchain reference structre*/
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_SWAPCHAIN_REF),
(IMG_VOID **)&psSwapChainRef, IMG_NULL,
@@ -950,10 +1239,10 @@ static PVRSRV_ERROR PVRSRVCreateDCSwapChainRefKM(PVRSRV_PER_PROCESS_DATA *psPerP
}
OSMemSet (psSwapChainRef, 0, sizeof(PVRSRV_DC_SWAPCHAIN_REF));
-
+ /* Bump refcount */
psSwapChain->ui32RefCount++;
-
+ /* Create reference resource */
psSwapChainRef->psSwapChain = psSwapChain;
psSwapChainRef->hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
@@ -1013,11 +1302,11 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_QUERY )
{
-
+ /* Query - use pui32SwapChainID as input */
psSwapChain = PVRSRVFindSharedDCSwapChainKM(psDCInfo, *pui32SwapChainID );
if( psSwapChain )
{
-
+ /* Create new reference */
eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
psSwapChain,
&psSwapChainRef);
@@ -1034,7 +1323,7 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
return PVRSRV_ERROR_FLIP_CHAIN_EXISTS;
}
-
+ /* Allocate swapchain control structure for srvkm */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_SWAPCHAIN),
(IMG_VOID **)&psSwapChain, IMG_NULL,
@@ -1046,7 +1335,7 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
}
OSMemSet (psSwapChain, 0, sizeof(PVRSRV_DC_SWAPCHAIN));
-
+ /* Create a command queue for the swapchain */
eError = PVRSRVCreateCommandQueueKM(1024, &psQueue);
if(eError != PVRSRV_OK)
{
@@ -1054,10 +1343,10 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
goto ErrorExit;
}
-
+ /* store the Queue */
psSwapChain->psQueue = psQueue;
-
+ /* Create a Sync Object for each surface in the swapchain */
for(i=0; i<ui32BufferCount; i++)
{
eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
@@ -1069,18 +1358,16 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
goto ErrorExit;
}
- psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
-
-
+ /* setup common device class info */
psSwapChain->asBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psDCInfo->psFuncTable->pfnGetBufferAddr;
psSwapChain->asBuffer[i].sDeviceClassBuffer.hDevMemContext = psDCInfo->hDevMemContext;
psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtDevice = psDCInfo->hExtDevice;
-
+ /* save off useful ptrs */
psSwapChain->asBuffer[i].psDCInfo = psDCInfo;
psSwapChain->asBuffer[i].psSwapChain = psSwapChain;
-
+ /* syncinfos must be passed as array of syncdata ptrs to the 3rd party driver */
apsSyncData[i] = (PVRSRV_SYNC_DATA*)psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
}
@@ -1109,7 +1396,7 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
psSwapChain->ui32MinSwapInterval = sDisplayInfo.ui32MinSwapInterval;
psSwapChain->ui32MaxSwapInterval = sDisplayInfo.ui32MaxSwapInterval;
-
+ /* call into the display device driver to create a swapchain */
eError = psDCInfo->psFuncTable->pfnCreateDCSwapChain(psDCInfo->hExtDevice,
ui32Flags,
psDstSurfAttrib,
@@ -1126,7 +1413,7 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
goto ErrorExit;
}
-
+ /* Create new reference */
eError = PVRSRVCreateDCSwapChainRefKM(psPerProc,
psSwapChain,
&psSwapChainRef);
@@ -1140,7 +1427,7 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
psSwapChain->ui32RefCount = 1;
psSwapChain->ui32Flags = ui32Flags;
-
+ /* Save pointer in DC structure if ti's shared struct */
if( ui32Flags & PVRSRV_CREATE_SWAPCHAIN_SHARED )
{
if(! psDCInfo->psDCSwapChainShared )
@@ -1155,10 +1442,10 @@ PVRSRV_ERROR PVRSRVCreateDCSwapChainKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
}
}
-
+ /* We create swapchain - pui32SwapChainID is output */
*pui32SwapChainID = psSwapChain->ui32SwapChainID;
-
+ /* return the swapchain reference handle */
*phSwapChainRef= (IMG_HANDLE)psSwapChainRef;
return eError;
@@ -1169,10 +1456,7 @@ ErrorExit:
{
if(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psSwapChain->asBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
@@ -1184,7 +1468,7 @@ ErrorExit:
if(psSwapChain)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_SWAPCHAIN), psSwapChain, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
return eError;
@@ -1289,7 +1573,8 @@ IMG_EXPORT
PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
IMG_HANDLE hSwapChainRef,
IMG_UINT32 *pui32BufferCount,
- IMG_HANDLE *phBuffer)
+ IMG_HANDLE *phBuffer,
+ IMG_SYS_PHYADDR *psPhyAddr)
{
PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
PVRSRV_DC_SWAPCHAIN *psSwapChain;
@@ -1297,7 +1582,7 @@ PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
PVRSRV_ERROR eError;
IMG_UINT32 i;
- if(!hDeviceKM || !hSwapChainRef || !phBuffer)
+ if(!hDeviceKM || !hSwapChainRef || !phBuffer || !psPhyAddr)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetDCBuffersKM: Invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
@@ -1306,7 +1591,7 @@ PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef)->psSwapChain;
-
+ /* call into the display device driver to get info */
eError = psDCInfo->psFuncTable->pfnGetDCBuffers(psDCInfo->hExtDevice,
psSwapChain->hExtSwapChain,
pui32BufferCount,
@@ -1314,15 +1599,42 @@ PVRSRV_ERROR PVRSRVGetDCBuffersKM(IMG_HANDLE hDeviceKM,
PVR_ASSERT(*pui32BufferCount <= PVRSRV_MAX_DC_SWAPCHAIN_BUFFERS);
-
-
-
+ /*
+ populate the srvkm's buffer structure with the 3rd party buffer handles
+ and return the services buffer handles
+ */
for(i=0; i<*pui32BufferCount; i++)
{
psSwapChain->asBuffer[i].sDeviceClassBuffer.hExtBuffer = ahExtBuffer[i];
phBuffer[i] = (IMG_HANDLE)&psSwapChain->asBuffer[i];
}
+#if defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS)
+ for(i = 0; i < *pui32BufferCount; i++)
+ {
+ IMG_UINT32 ui32ByteSize, ui32TilingStride;
+ IMG_SYS_PHYADDR *pPhyAddr;
+ IMG_BOOL bIsContiguous;
+ IMG_HANDLE hOSMapInfo;
+ IMG_VOID *pvVAddr;
+
+ eError = psDCInfo->psFuncTable->pfnGetBufferAddr(psDCInfo->hExtDevice,
+ ahExtBuffer[i],
+ &pPhyAddr,
+ &ui32ByteSize,
+ &pvVAddr,
+ &hOSMapInfo,
+ &bIsContiguous,
+ &ui32TilingStride);
+ if(eError != PVRSRV_OK)
+ {
+ break;
+ }
+
+ psPhyAddr[i] = *pPhyAddr;
+ }
+#endif /* defined(SUPPORT_GET_DC_BUFFERS_SYS_PHYADDRS) */
+
return eError;
}
@@ -1357,7 +1669,7 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
psBuffer = (PVRSRV_DC_BUFFER*)hBuffer;
psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
-
+ /* Validate swap interval against limits */
if(ui32SwapInterval < psBuffer->psSwapChain->ui32MinSwapInterval ||
ui32SwapInterval > psBuffer->psSwapChain->ui32MaxSwapInterval)
{
@@ -1381,25 +1693,19 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
#endif
-
+ /* get the queue from the buffer structure */
psQueue = psBuffer->psSwapChain->psQueue;
-
+ /* specify the syncs */
apsSrcSync[0] = psBuffer->sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
if(bAddReferenceToLast && psBuffer->psSwapChain->psLastFlipBuffer &&
psBuffer != psBuffer->psSwapChain->psLastFlipBuffer)
{
apsSrcSync[1] = psBuffer->psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
ui32NumSrcSyncs++;
}
-
+ /* insert the command (header) */
eError = PVRSRVInsertCommandKM (psQueue,
&psCommand,
psDCInfo->ui32DeviceID,
@@ -1408,42 +1714,68 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
IMG_NULL,
ui32NumSrcSyncs,
apsSrcSync,
- sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount));
+ sizeof(DISPLAYCLASS_FLIP_COMMAND) + (sizeof(IMG_RECT) * ui32ClipRectCount),
+ IMG_NULL,
+ IMG_NULL);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBufferKM: Failed to get space in queue"));
goto Exit;
}
-
+ /* setup the flip command */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
-
+ /* Ext Device Handle */
psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
-
+ /* Ext SwapChain Handle */
psFlipCmd->hExtSwapChain = psBuffer->psSwapChain->hExtSwapChain;
-
+ /* Ext Buffer Handle (Buffer to Flip to) */
psFlipCmd->hExtBuffer = psBuffer->sDeviceClassBuffer.hExtBuffer;
-
+ /* private tag */
psFlipCmd->hPrivateTag = hPrivateTag;
-
+ /* setup the clip rects */
psFlipCmd->ui32ClipRectCount = ui32ClipRectCount;
-
- psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND));
-
+ /* cliprect memory appends the command structure */
+ psFlipCmd->psClipRect = (IMG_RECT*)((IMG_UINT8*)psFlipCmd + sizeof(DISPLAYCLASS_FLIP_COMMAND)); // PRQA S 3305
+ /* copy the clip rects */
for(i=0; i<ui32ClipRectCount; i++)
{
psFlipCmd->psClipRect[i] = psClipRect[i];
}
-
+ /* number of vsyncs between successive flips */
psFlipCmd->ui32SwapInterval = ui32SwapInterval;
-
+ SysAcquireData(&psSysData);
+
+ /* Because we might be composing just software surfaces, without
+ * any SGX renders since the last frame, we won't necessarily
+ * have cleaned/flushed the CPU caches before the buffers need
+ * to be displayed.
+ *
+ * Doing so now is safe because InsertCommand bumped ROP2 on the
+ * affected buffers (preventing more SW renders starting) but the
+ * display won't start to process the buffers until SubmitCommand.
+ */
+ {
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+ }
+
+ /* submit the command */
eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
if (eError != PVRSRV_OK)
{
@@ -1451,9 +1783,9 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
goto Exit;
}
-
-
- SysAcquireData(&psSysData);
+ /*
+ Schedule an MISR to process it
+ */
eError = OSScheduleMISR(psSysData);
if (eError != PVRSRV_OK)
@@ -1462,7 +1794,7 @@ PVRSRV_ERROR PVRSRVSwapToDCBufferKM(IMG_HANDLE hDeviceKM,
goto Exit;
}
-
+ /* update the last flip buffer */
psBuffer->psSwapChain->psLastFlipBuffer = psBuffer;
Exit:
@@ -1475,6 +1807,288 @@ Exit:
return eError;
}
+typedef struct _CALLBACK_DATA_
+{
+ IMG_PVOID pvPrivData;
+ IMG_UINT32 ui32PrivDataLength;
+ IMG_PVOID ppvMemInfos;
+ IMG_UINT32 ui32NumMemInfos;
+} CALLBACK_DATA;
+
+static IMG_VOID FreePrivateData(IMG_HANDLE hCallbackData)
+{
+ CALLBACK_DATA *psCallbackData = hCallbackData;
+
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psCallbackData->ui32PrivDataLength,
+ psCallbackData->pvPrivData, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+ psCallbackData->ppvMemInfos, IMG_NULL);
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), hCallbackData, IMG_NULL);
+}
+
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVSwapToDCBuffer2KM(IMG_HANDLE hDeviceKM,
+ IMG_HANDLE hSwapChain,
+ IMG_UINT32 ui32SwapInterval,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfos,
+ PVRSRV_KERNEL_SYNC_INFO **ppsSyncInfos,
+ IMG_UINT32 ui32NumMemSyncInfos,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength)
+{
+ PVRSRV_KERNEL_SYNC_INFO **ppsCompiledSyncInfos;
+ IMG_UINT32 i, ui32NumCompiledSyncInfos;
+ DISPLAYCLASS_FLIP_COMMAND2 *psFlipCmd;
+ PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DC_SWAPCHAIN *psSwapChain;
+ PVRSRV_ERROR eError = PVRSRV_OK;
+ CALLBACK_DATA *psCallbackData;
+ PVRSRV_QUEUE_INFO *psQueue;
+ PVRSRV_COMMAND *psCommand;
+ IMG_PVOID *ppvMemInfos;
+ SYS_DATA *psSysData;
+
+ if(!hDeviceKM || !hSwapChain || !ppsMemInfos || !ppsSyncInfos || ui32NumMemSyncInfos < 1)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid parameters"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psSwapChain = ((PVRSRV_DC_SWAPCHAIN_REF*)hSwapChain)->psSwapChain;
+ psDCInfo = DCDeviceHandleToDCInfo(hDeviceKM);
+
+ /* Validate swap interval against limits */
+ if(ui32SwapInterval < psSwapChain->ui32MinSwapInterval ||
+ ui32SwapInterval > psSwapChain->ui32MaxSwapInterval)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Invalid swap interval. Requested %u, Allowed range %u-%u",
+ ui32SwapInterval, psSwapChain->ui32MinSwapInterval, psSwapChain->ui32MaxSwapInterval));
+ return PVRSRV_ERROR_INVALID_SWAPINTERVAL;
+ }
+
+ eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(CALLBACK_DATA),
+ (IMG_VOID **)&psCallbackData, IMG_NULL,
+ "PVRSRVSwapToDCBuffer2KM callback data");
+ if (eError != PVRSRV_OK)
+ {
+ return eError;
+ }
+
+ psCallbackData->pvPrivData = pvPrivData;
+ psCallbackData->ui32PrivDataLength = ui32PrivDataLength;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * ui32NumMemSyncInfos,
+ (IMG_VOID **)&ppvMemInfos, IMG_NULL,
+ "Swap Command Meminfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ psCallbackData->ppvMemInfos = IMG_NULL;
+ goto Exit;
+ }
+
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ ppvMemInfos[i] = ppsMemInfos[i];
+ }
+
+ psCallbackData->ppvMemInfos = ppvMemInfos;
+ psCallbackData->ui32NumMemInfos = ui32NumMemSyncInfos;
+
+ /* get the queue from the buffer structure */
+ psQueue = psSwapChain->psQueue;
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ if(psSwapChain->ppsLastSyncInfos)
+ {
+ IMG_UINT32 ui32NumUniqueSyncInfos = psSwapChain->ui32LastNumSyncInfos;
+ IMG_UINT32 j;
+
+ for(j = 0; j < psSwapChain->ui32LastNumSyncInfos; j++)
+ {
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ if(psSwapChain->ppsLastSyncInfos[j] == ppsSyncInfos[i])
+ {
+ psSwapChain->ppsLastSyncInfos[j] = IMG_NULL;
+ ui32NumUniqueSyncInfos--;
+ }
+ }
+ }
+
+ ui32NumCompiledSyncInfos = ui32NumMemSyncInfos + ui32NumUniqueSyncInfos;
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+ (IMG_VOID **)&ppsCompiledSyncInfos, IMG_NULL,
+ "Compiled syncinfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ goto Exit;
+ }
+
+ OSMemCopy(ppsCompiledSyncInfos, ppsSyncInfos, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos);
+ for(j = 0, i = ui32NumMemSyncInfos; j < psSwapChain->ui32LastNumSyncInfos; j++)
+ {
+ if(psSwapChain->ppsLastSyncInfos[j])
+ {
+ ppsCompiledSyncInfos[i] = psSwapChain->ppsLastSyncInfos[j];
+ i++;
+ }
+ }
+ }
+ else
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+ {
+ ppsCompiledSyncInfos = ppsSyncInfos;
+ ui32NumCompiledSyncInfos = ui32NumMemSyncInfos;
+ }
+
+ /* insert the command (header) */
+ eError = PVRSRVInsertCommandKM (psQueue,
+ &psCommand,
+ psDCInfo->ui32DeviceID,
+ DC_FLIP_COMMAND,
+ 0,
+ IMG_NULL,
+ ui32NumCompiledSyncInfos,
+ ppsCompiledSyncInfos,
+ sizeof(DISPLAYCLASS_FLIP_COMMAND2),
+ FreePrivateData,
+ psCallbackData);
+
+ if (ppsCompiledSyncInfos != ppsSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumCompiledSyncInfos,
+ (IMG_VOID *)ppsCompiledSyncInfos,
+ IMG_NULL);
+ }
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to get space in queue"));
+ goto Exit;
+ }
+
+ /* setup the flip command */
+ psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND2*)psCommand->pvData;
+
+ /* Ext Device Handle */
+ psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
+
+ /* Ext SwapChain Handle */
+ psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
+
+ /* number of vsyncs between successive flips */
+ psFlipCmd->ui32SwapInterval = ui32SwapInterval;
+
+ /* Opaque private data, if supplied */
+ psFlipCmd->pvPrivData = pvPrivData;
+ psFlipCmd->ui32PrivDataLength = ui32PrivDataLength;
+
+ psFlipCmd->ppsMemInfos = (PDC_MEM_INFO *)ppvMemInfos;
+ psFlipCmd->ui32NumMemInfos = ui32NumMemSyncInfos;
+
+ /* Even though this is "unused", we have to initialize it,
+ * as the display controller might NULL-test it.
+ */
+ psFlipCmd->hUnused = IMG_NULL;
+
+ SysAcquireData(&psSysData);
+
+ /* Because we might be composing just software surfaces, without
+ * any SGX renders since the last frame, we won't necessarily
+ * have cleaned/flushed the CPU caches before the buffers need
+ * to be displayed.
+ *
+ * Doing so now is safe because InsertCommand bumped ROP2 on the
+ * affected buffers (preventing more SW renders starting) but the
+ * display won't start to process the buffers until SubmitCommand.
+ */
+ {
+ if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
+ {
+ OSFlushCPUCacheKM();
+ }
+ else if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
+ {
+ OSCleanCPUCacheKM();
+ }
+
+ psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
+ }
+
+ /* submit the command */
+ eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to submit command"));
+ goto Exit;
+ }
+
+ /* The command has been submitted and so psCallbackData will be freed by the callback */
+ psCallbackData = IMG_NULL;
+
+ /*
+ Schedule an MISR to process it
+ */
+ eError = OSScheduleMISR(psSysData);
+
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to schedule MISR"));
+ goto Exit;
+ }
+
+#if !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+ /* Reallocate the syncinfo list if it was too small */
+ if (psSwapChain->ui32LastNumSyncInfos < ui32NumMemSyncInfos)
+ {
+ if (psSwapChain->ppsLastSyncInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_SYNC_INFO *) * psSwapChain->ui32LastNumSyncInfos,
+ psSwapChain->ppsLastSyncInfos, IMG_NULL);
+ }
+
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(PVRSRV_KERNEL_SYNC_INFO *) * ui32NumMemSyncInfos,
+ (IMG_VOID **)&psSwapChain->ppsLastSyncInfos, IMG_NULL,
+ "Last syncinfos") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCBuffer2KM: Failed to allocate space for meminfo list"));
+ goto Exit;
+ }
+ }
+
+ psSwapChain->ui32LastNumSyncInfos = ui32NumMemSyncInfos;
+
+ for(i = 0; i < ui32NumMemSyncInfos; i++)
+ {
+ psSwapChain->ppsLastSyncInfos[i] = ppsSyncInfos[i];
+ }
+#endif /* !defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED) */
+
+Exit:
+ if (psCallbackData)
+ {
+ if(psCallbackData->ppvMemInfos)
+ {
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(IMG_VOID *) * psCallbackData->ui32NumMemInfos,
+ psCallbackData->ppvMemInfos, IMG_NULL);
+ }
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(CALLBACK_DATA), psCallbackData, IMG_NULL);
+ }
+ if(eError == PVRSRV_ERROR_CANNOT_GET_QUEUE_SPACE)
+ {
+ eError = PVRSRV_ERROR_RETRY;
+ }
+
+ return eError;
+}
+
IMG_EXPORT
PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
@@ -1503,7 +2117,7 @@ PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
psSwapChainRef = (PVRSRV_DC_SWAPCHAIN_REF*)hSwapChainRef;
psSwapChain = psSwapChainRef->psSwapChain;
-
+ /* get the queue from the buffer structure */
psQueue = psSwapChain->psQueue;
#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
@@ -1521,25 +2135,19 @@ PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
#endif
-
+ /* specify the syncs */
apsSrcSync[0] = psDCInfo->sSystemBuffer.sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
if(bAddReferenceToLast && psSwapChain->psLastFlipBuffer)
{
-
+ /* Make sure we don't make a double dependency on the same server */
if (apsSrcSync[0] != psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo)
{
apsSrcSync[1] = psSwapChain->psLastFlipBuffer->sDeviceClassBuffer.psKernelSyncInfo;
-
-
-
ui32NumSrcSyncs++;
}
}
-
+ /* insert the command (header) */
eError = PVRSRVInsertCommandKM (psQueue,
&psCommand,
psDCInfo->ui32DeviceID,
@@ -1548,34 +2156,36 @@ PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
IMG_NULL,
ui32NumSrcSyncs,
apsSrcSync,
- sizeof(DISPLAYCLASS_FLIP_COMMAND));
+ sizeof(DISPLAYCLASS_FLIP_COMMAND),
+ IMG_NULL,
+ IMG_NULL);
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVSwapToDCSystemKM: Failed to get space in queue"));
goto Exit;
}
-
+ /* setup the flip command */
psFlipCmd = (DISPLAYCLASS_FLIP_COMMAND*)psCommand->pvData;
-
+ /* Ext Device Handle */
psFlipCmd->hExtDevice = psDCInfo->hExtDevice;
-
+ /* Ext SwapChain Handle */
psFlipCmd->hExtSwapChain = psSwapChain->hExtSwapChain;
-
+ /* Ext Buffer Handle (Buffer to Flip to) */
psFlipCmd->hExtBuffer = psDCInfo->sSystemBuffer.sDeviceClassBuffer.hExtBuffer;
-
+ /* private tag */
psFlipCmd->hPrivateTag = IMG_NULL;
-
+ /* setup the clip rects */
psFlipCmd->ui32ClipRectCount = 0;
psFlipCmd->ui32SwapInterval = 1;
-
+ /* submit the command */
eError = PVRSRVSubmitCommandKM (psQueue, psCommand);
if (eError != PVRSRV_OK)
{
@@ -1583,7 +2193,7 @@ PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
goto Exit;
}
-
+ /* Schedule an MISR to process it */
SysAcquireData(&psSysData);
eError = OSScheduleMISR(psSysData);
@@ -1593,7 +2203,7 @@ PVRSRV_ERROR PVRSRVSwapToDCSystemKM(IMG_HANDLE hDeviceKM,
goto Exit;
}
-
+ /* update the last flip buffer */
psSwapChain->psLastFlipBuffer = &psDCInfo->sSystemBuffer;
eError = PVRSRV_OK;
@@ -1609,6 +2219,26 @@ Exit:
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterSystemISRHandler
+
+ @Description
+
+ registers an external ISR to be called of the back of a system ISR
+
+ @Input ppfnISRHandler : ISR pointer
+
+ @Input hISRHandlerData : Callback data
+
+ @Input ui32ISRSourceMask : ISR Mask
+
+ @Input ui32DeviceID : unique device key
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
IMG_VOID *pvISRHandlerData,
@@ -1622,7 +2252,7 @@ PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
SysAcquireData(&psSysData);
-
+ /* Find Dev Node (just using the device id, ignore the class) */
psDevNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
@@ -1636,15 +2266,29 @@ PVRSRV_ERROR PVRSRVRegisterSystemISRHandler (PFN_ISR_HANDLER pfnISRHandler,
return PVRSRV_ERROR_NO_DEVICENODE_FOUND;
}
-
+ /* set up data before enabling the ISR */
psDevNode->pvISRData = (IMG_VOID*) pvISRHandlerData;
-
+ /* enable the ISR */
psDevNode->pfnDeviceISR = pfnISRHandler;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDCState_ForEachVaCb
+
+ @Description
+
+ If the device node is a display, calls its set state function.
+
+ @Input psDeviceNode - the device node
+ va - variable argument list with:
+ ui32State - the state to be set.
+
+******************************************************************************/
static
IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
@@ -1663,8 +2307,22 @@ IMG_VOID PVRSRVSetDCState_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDCState
+
+ @Description
+
+ Calls the display driver(s) to put them into the specified state.
+
+ @Input ui32State: new DC state - one of DC_STATE_*
+
+******************************************************************************/
IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
{
+/* PVRSRV_DISPLAYCLASS_INFO *psDCInfo;
+ PVRSRV_DEVICE_NODE *psDeviceNode; */
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
@@ -1674,7 +2332,50 @@ IMG_VOID IMG_CALLCONV PVRSRVSetDCState(IMG_UINT32 ui32State)
ui32State);
}
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuVAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_CPU_VIRTADDR *pVAddr)
+{
+ *pVAddr = psKernelMemInfo->pvLinAddrKM;
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetCpuPAddr(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_SIZE_T uByteOffset, IMG_CPU_PHYADDR *pPAddr)
+{
+ *pPAddr = OSMemHandleToCpuPAddr(psKernelMemInfo->sMemBlk.hOSMemHandle, uByteOffset);
+ return PVRSRV_OK;
+}
+
+static PVRSRV_ERROR
+PVRSRVDCMemInfoGetByteSize(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo,
+ IMG_SIZE_T *uByteSize)
+{
+ *uByteSize = psKernelMemInfo->uAllocSize;
+ return PVRSRV_OK;
+}
+
+static IMG_BOOL
+PVRSRVDCMemInfoIsPhysContig(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ return OSMemHandleIsPhysContig(psKernelMemInfo->sMemBlk.hOSMemHandle);
+}
+
+/*!
+******************************************************************************
+ @Function PVRGetDisplayClassJTable
+
+ @Description
+
+ Sets up function table for 3rd party Display Class Device to call through
+
+ @Input psJTable : pointer to function pointer table memory
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
{
@@ -1694,24 +2395,37 @@ IMG_BOOL PVRGetDisplayClassJTable(PVRSRV_DC_DISP2SRV_KMJTABLE *psJTable)
#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
psJTable->pfnPVRSRVFreeCmdCompletePacket = &PVRSRVFreeCommandCompletePacketKM;
#endif
-
+ psJTable->pfnPVRSRVDCMemInfoGetCpuVAddr = &PVRSRVDCMemInfoGetCpuVAddr;
+ psJTable->pfnPVRSRVDCMemInfoGetCpuPAddr = &PVRSRVDCMemInfoGetCpuPAddr;
+ psJTable->pfnPVRSRVDCMemInfoGetByteSize = &PVRSRVDCMemInfoGetByteSize;
+ psJTable->pfnPVRSRVDCMemInfoIsPhysContig = &PVRSRVDCMemInfoIsPhysContig;
return IMG_TRUE;
}
+/******************************************************************************
+
+ @Function PVRSRVCloseBCDeviceKM
+
+ @Description
+
+ Closes a connection to the Buffer Class device
+
+ @Input hDeviceKM : device handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM,
- IMG_BOOL bResManCallback)
+PVRSRV_ERROR PVRSRVCloseBCDeviceKM (IMG_HANDLE hDeviceKM)
{
PVRSRV_ERROR eError;
PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *psBCPerContextInfo;
- PVR_UNREFERENCED_PARAMETER(bResManCallback);
-
psBCPerContextInfo = (PVRSRV_BUFFERCLASS_PERCONTEXT_INFO *)hDeviceKM;
-
+ /* Remove the item from the resman list and trigger the callback. */
eError = ResManFreeResByPtr(psBCPerContextInfo->hResItem, CLEANUP_WITH_POLL);
return eError;
@@ -1750,22 +2464,19 @@ static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
psBCInfo->ui32RefCount--;
if(psBCInfo->ui32RefCount == 0)
{
-
+ /* close the external device */
psBCInfo->psFuncTable->pfnCloseBCDevice(psBCInfo->ui32DeviceID, psBCInfo->hExtDevice);
-
+ /* free syncinfos */
for(i=0; i<psBCInfo->ui32BufferCount; i++)
{
if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
-
+ /* free buffers */
if(psBCInfo->psBuffer)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER) * psBCInfo->ui32BufferCount, psBCInfo->psBuffer, IMG_NULL);
@@ -1774,12 +2485,31 @@ static PVRSRV_ERROR CloseBCDeviceCallBack(IMG_PVOID pvParam,
}
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BUFFERCLASS_PERCONTEXT_INFO), psBCPerContextInfo, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpenBCDeviceKM
+
+ @Description
+
+ Opens a connection to the Buffer Class device, associating the connection
+ with a Device Memory Context for a services managed device
+
+ @Input psPerProc : Per-process data
+ @Input ui32DeviceID : unique device index
+ @Input hDevCookie : devcookie used to derive the Device Memory
+ Context into BC surfaces will be mapped into
+ @Outut phDeviceKM : handle to the DC device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 ui32DeviceID,
@@ -1801,7 +2531,7 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
SysAcquireData(&psSysData);
-
+ /* find the matching devicenode */
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
@@ -1815,9 +2545,13 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
}
psBCInfo = (PVRSRV_BUFFERCLASS_INFO*)psDeviceNode->pvDevice;
-
-
-
+/*
+FoundDevice:
+*/
+ /*
+ Allocate the per-context BC Info before calling the external device,
+ to make error handling easier.
+ */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*psBCPerContextInfo),
(IMG_VOID **)&psBCPerContextInfo, IMG_NULL,
@@ -1834,10 +2568,10 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
+ /* store the device kernel context to map into */
psBCInfo->hDevMemContext = (IMG_HANDLE)psDeviceNode->sDevMemoryInfo.pBMKernelContext;
-
+ /* open the external device */
eError = psBCInfo->psFuncTable->pfnOpenBCDevice(ui32DeviceID, &psBCInfo->hExtDevice);
if(eError != PVRSRV_OK)
{
@@ -1845,7 +2579,7 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
return eError;
}
-
+ /* get information about the buffers */
eError = psBCInfo->psFuncTable->pfnGetBCInfo(psBCInfo->hExtDevice, &sBufferInfo);
if(eError != PVRSRV_OK)
{
@@ -1853,11 +2587,10 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
return eError;
}
-
+ /* interpret and store info */
psBCInfo->ui32BufferCount = sBufferInfo.ui32BufferCount;
-
-
+ /* allocate BC buffers */
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_BC_BUFFER) * sBufferInfo.ui32BufferCount,
(IMG_VOID **)&psBCInfo->psBuffer,
@@ -1874,7 +2607,7 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
for(i=0; i<psBCInfo->ui32BufferCount; i++)
{
-
+ /* create a syncinfo for the device's system surface */
eError = PVRSRVAllocSyncInfoKM(IMG_NULL,
psBCInfo->hDevMemContext,
&psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
@@ -1883,12 +2616,11 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
PVR_DPF((PVR_DBG_ERROR,"PVRSRVOpenBCDeviceKM: Failed sync info alloc"));
goto ErrorExit;
}
-
- psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount++;
-
-
-
+ /*
+ get the buffers from the buffer class
+ drivers by index, passing-in the syncdata objects
+ */
eError = psBCInfo->psFuncTable->pfnGetBCBuffer(psBCInfo->hExtDevice,
i,
psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->psSyncData,
@@ -1899,7 +2631,7 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
goto ErrorExit;
}
-
+ /* setup common device class info */
psBCInfo->psBuffer[i].sDeviceClassBuffer.pfnGetBufferAddr = psBCInfo->psFuncTable->pfnGetBufferAddr;
psBCInfo->psBuffer[i].sDeviceClassBuffer.hDevMemContext = psBCInfo->hDevMemContext;
psBCInfo->psBuffer[i].sDeviceClassBuffer.hExtDevice = psBCInfo->hExtDevice;
@@ -1914,26 +2646,23 @@ PVRSRV_ERROR PVRSRVOpenBCDeviceKM (PVRSRV_PER_PROCESS_DATA *psPerProc,
0,
&CloseBCDeviceCallBack);
-
+ /* return a reference to the BCPerContextInfo */
*phDeviceKM = (IMG_HANDLE)psBCPerContextInfo;
return PVRSRV_OK;
ErrorExit:
-
+ /* free syncinfos */
for(i=0; i<psBCInfo->ui32BufferCount; i++)
{
if(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo)
{
- if (--psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo->ui32RefCount == 0)
- {
- PVRSRVFreeSyncInfoKM(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo);
- }
+ PVRSRVKernelSyncInfoDecRef(psBCInfo->psBuffer[i].sDeviceClassBuffer.psKernelSyncInfo, IMG_NULL);
}
}
-
+ /* free buffers */
if(psBCInfo->psBuffer)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_BC_BUFFER), psBCInfo->psBuffer, IMG_NULL);
@@ -1946,6 +2675,20 @@ ErrorExit:
+/******************************************************************************
+
+ @Function PVRSRVGetBCInfoKM
+
+ @Description
+
+ Gets Buffer Class device Info
+
+ @Input hDeviceKM : device handle
+ @Output psBufferInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
BUFFER_INFO *psBufferInfo)
@@ -1973,6 +2716,20 @@ PVRSRV_ERROR PVRSRVGetBCInfoKM (IMG_HANDLE hDeviceKM,
}
+/******************************************************************************
+
+ @Function PVRSRVGetBCBufferKM
+
+ @Description
+
+ Gets Buffer Class Buffer Handle
+
+ @Input hDeviceKM : device handle
+ @Output psBufferInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
IMG_UINT32 ui32BufferIndex,
@@ -2002,6 +2759,20 @@ PVRSRV_ERROR PVRSRVGetBCBufferKM (IMG_HANDLE hDeviceKM,
}
+/*!
+******************************************************************************
+
+ @Function PVRGetBufferClassJTable
+
+ @Description
+
+ Sets up function table for 3rd party Buffer Class Device to call through
+
+ @Input psJTable : pointer to function pointer table memory
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
{
@@ -2014,3 +2785,6 @@ IMG_BOOL PVRGetBufferClassJTable(PVRSRV_BC_BUFFER2SRV_KMJTABLE *psJTable)
return IMG_TRUE;
}
+/******************************************************************************
+ End of file (deviceclass.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/deviceid.h b/sgx/services4/srvkm/common/deviceid.h
index 9a7bdb3..e4f0b4c 100644
--- a/sgx/services4/srvkm/common/deviceid.h
+++ b/sgx/services4/srvkm/common/deviceid.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device ID helpers
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __DEVICEID_H__
#define __DEVICEID_H__
@@ -33,4 +49,4 @@
PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID);
PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID);
-#endif
+#endif /* __DEVICEID_H__ */
diff --git a/sgx/services4/srvkm/common/devicemem.c b/sgx/services4/srvkm/common/devicemem.c
index 5642640..e193396 100644
--- a/sgx/services4/srvkm/common/devicemem.c
+++ b/sgx/services4/srvkm/common/devicemem.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device addressable memory functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device addressable memory APIs
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <stddef.h>
@@ -38,6 +55,11 @@
#include "mmap.h"
#endif
+#if defined(SUPPORT_ION)
+#include "ion.h"
+#include "env_perproc.h"
+#endif
+
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
# include <linux/omap_drv.h>
# include "perproc.h"
@@ -45,21 +67,37 @@
extern int pvr_mapper_id;
#endif
+/* local function prototypes */
static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
- IMG_HANDLE hDevMemHeap,
- IMG_UINT32 ui32Flags,
- IMG_SIZE_T ui32Size,
- IMG_SIZE_T ui32Alignment,
- PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
-
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo);
+
+/* local structures */
+
+/*
+ structure stored in resman to store references
+ to the SRC and DST meminfo
+*/
typedef struct _RESMAN_MAP_DEVICE_MEM_DATA_
{
-
+ /* the DST meminfo created by the map */
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
-
+ /* SRC meminfo */
PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo;
} RESMAN_MAP_DEVICE_MEM_DATA;
+/*
+ map device class resman memory storage structure
+*/
typedef struct _PVRSRV_DC_MAPINFO_
{
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
@@ -71,6 +109,22 @@ typedef struct _PVRSRV_DC_MAPINFO_
static IMG_UINT32 g_ui32SyncUID = 0;
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDeviceMemHeapsKM
+
+ @Description
+
+ Gets the device shared memory heaps
+
+ @Input hDevCookie :
+ @Output phDevMemContext : ptr to handle to memory context
+ @Output psHeapInfo : ptr to array of heap info
+
+ @Return PVRSRV_DEVICE_NODE, valid devnode or IMG_NULL
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
#if defined (SUPPORT_SID_INTERFACE)
@@ -93,22 +147,24 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
+ /* Setup useful pointers */
ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
-
+ /* check we don't exceed the max number of heaps */
PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
-
+ /* retrieve heap information */
for(i=0; i<ui32HeapCount; i++)
{
-
+ /* return information about the heap */
psHeapInfo[i].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
psHeapInfo[i].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
psHeapInfo[i].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
psHeapInfo[i].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
psHeapInfo[i].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ /* (XTileStride > 0) denotes a tiled heap */
+ psHeapInfo[i].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
}
for(; i < PVRSRV_MAX_CLIENT_HEAPS; i++)
@@ -120,6 +176,24 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapsKM(IMG_HANDLE hDevCookie,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVCreateDeviceMemContextKM
+
+ @Description
+
+ Creates a device memory context
+
+ @Input hDevCookie :
+ @Input psPerProc : Per-process data
+ @Output phDevMemContext : ptr to handle to memory context
+ @Output pui32ClientHeapCount : ptr to heap count
+ @Output psHeapInfo : ptr to array of heap info
+
+ @Return PVRSRV_DEVICE_NODE, valid devnode or IMG_NULL
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCookie,
PVRSRV_PER_PROCESS_DATA *psPerProc,
@@ -154,17 +228,20 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCook
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
-
+ /*
+ Setup useful pointers
+ */
ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
-
-
+ /*
+ check we don't exceed the max number of heaps
+ */
PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
-
-
+ /*
+ Create a memory context for the caller
+ */
hDevMemContext = BM_CreateContext(psDeviceNode,
&sPDDevPAddr,
psPerProc,
@@ -175,19 +252,25 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCook
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* create the per context heaps */
for(i=0; i<ui32HeapCount; i++)
{
switch(psDeviceMemoryHeap[i].DevMemHeapType)
{
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* return information about the heap */
psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ #if defined(SUPPORT_MEMORY_TILING)
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ #else
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+ #endif
+
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_TRUE;
#endif
@@ -211,12 +294,17 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCook
hDevMemHeap = IMG_NULL;
}
-
+ /* return information about the heap */
psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ #if defined(SUPPORT_MEMORY_TILING)
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
+ #else
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = 0;
+ #endif
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_FALSE;
#endif
@@ -227,7 +315,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateDeviceMemContextKM(IMG_HANDLE hDevCook
}
}
-
+ /* return shared_exported and per context heap information to the caller */
*pui32ClientHeapCount = ui32ClientHeapCount;
*phDevMemContext = hDevMemContext;
@@ -247,6 +335,23 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyDeviceMemContextKM(IMG_HANDLE hDevCookie,
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetDeviceMemHeapInfoKM
+
+ @Description
+
+ gets heap info
+
+ @Input hDevCookie :
+ @Input hDevMemContext : ptr to handle to memory context
+ @Output pui32ClientHeapCount : ptr to heap count
+ @Output psHeapInfo : ptr to array of heap info
+
+ @Return
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext,
@@ -277,28 +382,31 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
-
-
+ /*
+ Setup useful pointers
+ */
ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
-
-
+ /*
+ check we don't exceed the max number of heaps
+ */
PVR_ASSERT(ui32HeapCount <= PVRSRV_MAX_CLIENT_HEAPS);
-
+ /* create the per context heaps */
for(i=0; i<ui32HeapCount; i++)
{
switch(psDeviceMemoryHeap[i].DevMemHeapType)
{
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* return information about the heap */
psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
psHeapInfo[ui32ClientHeapCount].hDevMemHeap = psDeviceMemoryHeap[i].hDevMemHeap;
psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_TRUE;
#endif
@@ -322,12 +430,13 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie
hDevMemHeap = IMG_NULL;
}
-
+ /* return information about the heap */
psHeapInfo[ui32ClientHeapCount].ui32HeapID = psDeviceMemoryHeap[i].ui32HeapID;
psHeapInfo[ui32ClientHeapCount].hDevMemHeap = hDevMemHeap;
psHeapInfo[ui32ClientHeapCount].sDevVAddrBase = psDeviceMemoryHeap[i].sDevVAddrBase;
psHeapInfo[ui32ClientHeapCount].ui32HeapByteSize = psDeviceMemoryHeap[i].ui32HeapSize;
psHeapInfo[ui32ClientHeapCount].ui32Attribs = psDeviceMemoryHeap[i].ui32Attribs;
+ psHeapInfo[ui32ClientHeapCount].ui32XTileStride = psDeviceMemoryHeap[i].ui32XTileStride;
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
pbShared[ui32ClientHeapCount] = IMG_FALSE;
#endif
@@ -338,23 +447,57 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetDeviceMemHeapInfoKM(IMG_HANDLE hDevCookie
}
}
-
+ /* return shared_exported and per context heap information to the caller */
*pui32ClientHeapCount = ui32ClientHeapCount;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function AllocDeviceMem
+
+ @Description
+
+ Allocates device memory
+
+ @Input hDevCookie :
+
+ @Input hDevMemHeap
+
+ @Input ui32Flags : Some combination of PVRSRV_MEM_ flags
+
+ @Input ui32Size : Number of bytes to allocate
+
+ @Input ui32Alignment : Alignment of allocation
+
+ @Input pvPrivData : Opaque private data passed through to allocator
+
+ @Input ui32PrivDataLength : Length of opaque private data
+
+ @Output **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
- IMG_HANDLE hDevMemHeap,
- IMG_UINT32 ui32Flags,
- IMG_SIZE_T ui32Size,
- IMG_SIZE_T ui32Alignment,
- PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
{
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
BM_HANDLE hBuffer;
-
+ /* Pointer to implementation details within the mem_info */
PVRSRV_MEMBLK *psMemBlock;
IMG_BOOL bBMError;
@@ -375,7 +518,7 @@ static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
psMemBlock = &(psMemInfo->sMemBlk);
-
+ /* BM supplied Device Virtual Address with physical backing RAM */
psMemInfo->ui32Flags = ui32Flags | PVRSRV_MEM_RAM_BACKED_ALLOCATION;
bBMError = BM_Alloc (hDevMemHeap,
@@ -383,42 +526,59 @@ static PVRSRV_ERROR AllocDeviceMem(IMG_HANDLE hDevCookie,
ui32Size,
&psMemInfo->ui32Flags,
IMG_CAST_TO_DEVVADDR_UINT(ui32Alignment),
+ pvPrivData,
+ ui32PrivDataLength,
+ ui32ChunkSize,
+ ui32NumVirtChunks,
+ ui32NumPhysChunks,
+ pabMapChunk,
&hBuffer);
if (!bBMError)
{
PVR_DPF((PVR_DBG_ERROR,"AllocDeviceMem: BM_Alloc Failed"));
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
- psMemInfo->uAllocSize = ui32Size;
+ if (ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ psMemInfo->uAllocSize = ui32ChunkSize * ui32NumVirtChunks;
+ }
+ else
+ {
+ psMemInfo->uAllocSize = ui32Size;
+ }
-
+ /* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
+ /*
+ * Setup the output.
+ */
*ppsMemInfo = psMemInfo;
-
+ /*
+ * And I think we're done for now....
+ */
return (PVRSRV_OK);
}
-static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL bFromAllocator)
+static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
{
BM_HANDLE hBuffer;
@@ -429,23 +589,27 @@ static PVRSRV_ERROR FreeDeviceMem2(PVRSRV_KERNEL_MEM_INFO *psMemInfo, IMG_BOOL b
hBuffer = psMemInfo->sMemBlk.hBuffer;
-
- if (bFromAllocator)
- BM_Free(hBuffer, psMemInfo->ui32Flags);
- else
- BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+ switch(eCallbackOrigin)
+ {
+ case PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR:
+ BM_Free(hBuffer, psMemInfo->ui32Flags);
+ break;
+ case PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER:
+ BM_FreeExport(hBuffer, psMemInfo->ui32Flags);
+ break;
+ default:
+ break;
+ }
-
- if ((psMemInfo->pvSysBackupBuffer) && bFromAllocator)
+ if (psMemInfo->pvSysBackupBuffer &&
+ eCallbackOrigin == PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR)
{
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
psMemInfo->pvSysBackupBuffer = IMG_NULL;
}
if (psMemInfo->ui32RefCount == 0)
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
return(PVRSRV_OK);
}
@@ -461,23 +625,32 @@ static PVRSRV_ERROR FreeDeviceMem(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
hBuffer = psMemInfo->sMemBlk.hBuffer;
-
BM_Free(hBuffer, psMemInfo->ui32Flags);
if(psMemInfo->pvSysBackupBuffer)
{
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, psMemInfo->uAllocSize, psMemInfo->pvSysBackupBuffer, IMG_NULL);
psMemInfo->pvSysBackupBuffer = IMG_NULL;
}
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
return(PVRSRV_OK);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocSyncInfoKM
+
+ @Description
+
+ Allocates a sync info
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext,
@@ -500,35 +673,47 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
- psKernelSyncInfo->ui32RefCount = 0;
-
+ eError = OSAtomicAlloc(&psKernelSyncInfo->pvRefCount);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to allocate atomic"));
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ /* Get the devnode from the devheap */
pBMContext = (BM_CONTEXT*)hDevMemContext;
psDevMemoryInfo = &pBMContext->psDeviceNode->sDevMemoryInfo;
-
+ /* and choose a heap for the syncinfo */
hSyncDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[psDevMemoryInfo->ui32SyncHeapID].hDevMemHeap;
-
-
-
+ /*
+ Cache consistent flag would be unnecessary if the heap attributes were
+ changed to specify it.
+ */
eError = AllocDeviceMem(hDevCookie,
hSyncDevMemHeap,
PVRSRV_MEM_CACHE_CONSISTENT,
sizeof(PVRSRV_SYNC_DATA),
sizeof(IMG_UINT32),
+ IMG_NULL,
+ 0,
+ 0, 0, 0, IMG_NULL, /* Sparse mapping args, not required */
&psKernelSyncInfo->psSyncDataMemInfoKM);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAllocSyncInfoKM: Failed to alloc memory"));
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* init sync data */
psKernelSyncInfo->psSyncData = psKernelSyncInfo->psSyncDataMemInfoKM->pvLinAddrKM;
psSyncData = psKernelSyncInfo->psSyncData;
@@ -536,8 +721,11 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
psSyncData->ui32WriteOpsComplete = 0;
psSyncData->ui32ReadOpsPending = 0;
psSyncData->ui32ReadOpsComplete = 0;
+ psSyncData->ui32ReadOps2Pending = 0;
+ psSyncData->ui32ReadOps2Complete = 0;
psSyncData->ui32LastOpDumpVal = 0;
psSyncData->ui32LastReadOpDumpVal = 0;
+ psSyncData->ui64LastWrite = 0;
#if defined(PDUMP)
PDUMPCOMMENT("Allocating kernel sync object");
@@ -551,244 +739,177 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVAllocSyncInfoKM(IMG_HANDLE hDevCookie,
psKernelSyncInfo->sWriteOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32WriteOpsComplete);
psKernelSyncInfo->sReadOpsCompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOpsComplete);
+ psKernelSyncInfo->sReadOps2CompleteDevVAddr.uiAddr = psKernelSyncInfo->psSyncDataMemInfoKM->sDevVAddr.uiAddr + offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete);
psKernelSyncInfo->ui32UID = g_ui32SyncUID++;
- psKernelSyncInfo->hSmartCache = NULL;
-
+ /* syncinfo meminfo has no syncinfo! */
psKernelSyncInfo->psSyncDataMemInfoKM->psKernelSyncInfo = IMG_NULL;
-
+ OSAtomicInc(psKernelSyncInfo->pvRefCount);
+
+ /* return result */
*ppsKernelSyncInfo = psKernelSyncInfo;
return PVRSRV_OK;
}
-
IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+IMG_VOID PVRSRVAcquireSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
{
- PVRSRV_ERROR eError;
+ OSAtomicInc(psKernelSyncInfo->pvRefCount);
+}
- if (psKernelSyncInfo->ui32RefCount != 0)
- {
- PVR_DPF((PVR_DBG_ERROR, "oops: sync info ref count not zero at destruction"));
-
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
+/*!
+******************************************************************************
- eError = FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
- (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
-
+ @Function PVRSRVFreeSyncInfoKM
- return eError;
-}
+ @Description
-static IMG_VOID freeWrapped(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
-{
- IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
+ Frees a sync info
-
- if(psMemInfo->sMemBlk.psIntSysPAddr)
- {
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
- psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
- }
+ @Return PVRSRV_ERROR :
- if(hOSWrapMem)
+******************************************************************************/
+IMG_EXPORT
+IMG_VOID IMG_CALLCONV PVRSRVReleaseSyncInfoKM(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
+{
+ if (OSAtomicDecAndTest(psKernelSyncInfo->pvRefCount))
{
- OSReleasePhysPageAddr(hOSWrapMem);
+ FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ /* Catch anyone who is trying to access the freed structure */
+ psKernelSyncInfo->psSyncDataMemInfoKM = IMG_NULL;
+ psKernelSyncInfo->psSyncData = IMG_NULL;
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
+ (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
-#if defined (PVRSRV_FLUSH_KERNEL_OPS_LAST_ONLY)
-static
-PVRSRV_ERROR _PollUntilAtLeast(volatile IMG_UINT32* pui32WatchedValue,
- IMG_UINT32 ui32MinimumValue,
- IMG_UINT32 ui32Waitus,
- IMG_UINT32 ui32Tries)
-{
- PVRSRV_ERROR eError;
- IMG_INT32 iDiff;
+ @Function freeExternal
- for(;;)
- {
- SYS_DATA *psSysData = SysAcquireDataNoCheck();
- iDiff = *pui32WatchedValue - ui32MinimumValue;
+ @Description
- if (iDiff >= 0)
- {
- eError = PVRSRV_OK;
- break;
- }
+ Code for freeing meminfo elements that are specific to external types memory
- if(!ui32Tries)
- {
- eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
- break;
- }
+ @Input psMemInfo : Kernel meminfo
- ui32Tries--;
+ @Return PVRSRV_ERROR :
-
- if (psSysData->psGlobalEventObject)
- {
- IMG_HANDLE hOSEventKM;
- if(psSysData->psGlobalEventObject)
- {
- eError = OSEventObjectOpenKM(psSysData->psGlobalEventObject, &hOSEventKM);
- if (eError |= PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "_PollUntilAtLeast: OSEventObjectOpen failed"));
- goto Exit;
- }
- eError = OSEventObjectWaitKM(hOSEventKM);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "_PollUntilAtLeast: PVRSRVEventObjectWait failed"));
- goto Exit;
- }
- eError = OSEventObjectCloseKM(psSysData->psGlobalEventObject, hOSEventKM);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "_PollUntilAtLeast: OSEventObjectClose failed"));
- }
- }
- }
- }
-Exit:
- return eError;
-}
+******************************************************************************/
-static PVRSRV_ERROR FlushKernelOps(PVRSRV_SYNC_DATA *psSyncData)
+static IMG_VOID freeExternal(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
- PVRSRV_ERROR eError;
+ IMG_HANDLE hOSWrapMem = psMemInfo->sMemBlk.hOSWrapMem;
- if(!psSyncData)
+ /* free the page addr array if req'd */
+ if(psMemInfo->sMemBlk.psIntSysPAddr)
{
- PVR_DPF((PVR_DBG_ERROR, "FlushKernelOps: invalid psSyncData"));
- return PVRSRV_ERROR_INVALID_PARAMS;
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psMemInfo->sMemBlk.psIntSysPAddr, IMG_NULL);
+ psMemInfo->sMemBlk.psIntSysPAddr = IMG_NULL;
}
-
-
-
-
-
+ /* Mem type dependent stuff */
+ if (psMemInfo->memType == PVRSRV_MEMTYPE_WRAPPED)
+ {
+ if(hOSWrapMem)
+ {
+ OSReleasePhysPageAddr(hOSWrapMem);
+ }
+ }
+#if defined(SUPPORT_ION)
+ else if (psMemInfo->memType == PVRSRV_MEMTYPE_ION)
+ {
+ if (hOSWrapMem)
+ {
+ IonUnimportBufferAndReleasePhysAddr(hOSWrapMem);
+ }
+ }
+#endif
+}
+/*!
+******************************************************************************
+ @Function FreeMemCallBackCommon
+ @Description
- eError = _PollUntilAtLeast(&psSyncData->ui32ReadOpsComplete,
- psSyncData->ui32ReadOpsPending,
- MAX_HW_TIME_US/WAIT_TRY_COUNT,
- WAIT_TRY_COUNT);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FlushClientOps: Read ops pending timeout"));
- PVR_DBG_BREAK;
- return eError;
- }
+ Common code for freeing device mem (called for freeing, unwrapping and unmapping)
- eError = _PollUntilAtLeast(&psSyncData->ui32WriteOpsComplete,
- psSyncData->ui32WriteOpsPending,
- MAX_HW_TIME_US/WAIT_TRY_COUNT,
- WAIT_TRY_COUNT);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FlushClientOps: Write ops pending timeout"));
- PVR_DBG_BREAK;
- }
+ @Input psMemInfo : Kernel meminfo
+ @Input ui32Param : packet size
+ @Input uibFromAllocatorParam : Are we being called by the original allocator?
- return eError;
-}
-#endif
+ @Return PVRSRV_ERROR :
-static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
- IMG_UINT32 ui32Param,
- IMG_BOOL bFromAllocator)
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN eCallbackOrigin)
{
PVRSRV_ERROR eError = PVRSRV_OK;
PVR_UNREFERENCED_PARAMETER(ui32Param);
-
- psMemInfo->ui32RefCount--;
+ /* decrement the refcount */
+ PVRSRVKernelMemInfoDecRef(psMemInfo);
-
- if(((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) != 0) && (bFromAllocator == IMG_TRUE))
+ /* check no other processes has this meminfo mapped */
+ if (psMemInfo->ui32RefCount == 0)
{
+ if((psMemInfo->ui32Flags & PVRSRV_MEM_EXPORTED) != 0)
+ {
#if defined (SUPPORT_SID_INTERFACE)
- IMG_SID hMemInfo = 0;
+ IMG_SID hMemInfo = 0;
#else
- IMG_HANDLE hMemInfo = IMG_NULL;
+ IMG_HANDLE hMemInfo = IMG_NULL;
#endif
-
- eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
- &hMemInfo,
- psMemInfo,
- PVRSRV_HANDLE_TYPE_MEM_INFO);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
- return eError;
- }
-
-
- eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
- hMemInfo,
- PVRSRV_HANDLE_TYPE_MEM_INFO);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
- return eError;
- }
- }
-
-
- if (psMemInfo->ui32RefCount == 0)
- {
-#if defined (PVRSRV_FLUSH_KERNEL_OPS_LAST_ONLY)
- if (psMemInfo->psKernelSyncInfo)
- {
- if (psMemInfo->sShareMemWorkaround.bInUse)
+ /* find the handle */
+ eError = PVRSRVFindHandle(KERNEL_HANDLE_BASE,
+ &hMemInfo,
+ psMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
{
-
- if (BM_XProcWorkaroundGetRefCount(psMemInfo->sShareMemWorkaround.ui32ShareIndex)
- == 1)
- {
- FlushKernelOps(psMemInfo->psKernelSyncInfo->psSyncData);
- }
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: can't find exported meminfo in the global handle list"));
+ return eError;
}
- else
- {
-
-
-
-
-
-
-
- FlushKernelOps(psMemInfo->psKernelSyncInfo->psSyncData);
+ /* release the handle */
+ eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: PVRSRVReleaseHandle failed for exported meminfo"));
+ return eError;
}
}
-#endif
+
switch(psMemInfo->memType)
{
-
+ /* Fall through: Free only what we should for each memory type */
case PVRSRV_MEMTYPE_WRAPPED:
- freeWrapped(psMemInfo);
+ case PVRSRV_MEMTYPE_ION:
+ freeExternal(psMemInfo);
case PVRSRV_MEMTYPE_DEVICE:
+ case PVRSRV_MEMTYPE_DEVICECLASS:
if (psMemInfo->psKernelSyncInfo)
{
- psMemInfo->psKernelSyncInfo->ui32RefCount--;
-
- if (psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
+ /* note: we have to inline PVRSRVReleaseSyncInfoKM here
+ * because we need clean up the GEM obj's ptr to the
+ * sync obj.. need to see if we can find a cleaner
+ * way..
+ */
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo = psMemInfo->psKernelSyncInfo;
+ if (OSAtomicDecAndTest(psKernelSyncInfo->pvRefCount))
{
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
struct drm_gem_object *buf =
@@ -799,16 +920,17 @@ static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
omap_gem_set_sync_object(buf, NULL);
}
#endif
- if (psMemInfo->psKernelSyncInfo->hSmartCache)
- {
- BM_UnregisterSmart(psMemInfo->sMemBlk.hBuffer,
- psMemInfo->psKernelSyncInfo->hSmartCache);
- PVRMMapFreeSmart(psMemInfo->psKernelSyncInfo->hSmartCache);
- }
- eError = PVRSRVFreeSyncInfoKM(psMemInfo->psKernelSyncInfo);
+
+ FreeDeviceMem(psKernelSyncInfo->psSyncDataMemInfoKM);
+
+ /* Catch anyone who is trying to access the freed structure */
+ psKernelSyncInfo->psSyncDataMemInfoKM = IMG_NULL;
+ psKernelSyncInfo->psSyncData = IMG_NULL;
+ OSAtomicFree(psKernelSyncInfo->pvRefCount);
+ (IMG_VOID)OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_SYNC_INFO), psKernelSyncInfo, IMG_NULL);
+ /*not nulling pointer, copy on stack*/
}
}
- case PVRSRV_MEMTYPE_DEVICECLASS:
break;
default:
PVR_DPF((PVR_DBG_ERROR, "FreeMemCallBackCommon: Unknown memType"));
@@ -816,15 +938,36 @@ static PVRSRV_ERROR FreeMemCallBackCommon(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
}
}
-
+ /*
+ * FreeDeviceMem2 will do the right thing, freeing
+ * the virtual memory info when the allocator calls
+ * but only releaseing the physical pages when everyone
+ * is done.
+ */
+
if (eError == PVRSRV_OK)
{
- eError = FreeDeviceMem2(psMemInfo, bFromAllocator);
+ eError = FreeDeviceMem2(psMemInfo, eCallbackOrigin);
}
return eError;
}
+/*!
+******************************************************************************
+
+ @Function FreeDeviceMemCallBack
+
+ @Description
+
+ ResMan call back to free device memory
+
+ @Input pvParam : data packet
+ @Input ui32Param : packet size
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
@@ -833,10 +976,25 @@ static PVRSRV_ERROR FreeDeviceMemCallBack(IMG_PVOID pvParam,
PVR_UNREFERENCED_PARAMETER(bDummy);
- return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFreeDeviceMemKM
+
+ @Description
+
+ Frees memory allocated with PVRAllocDeviceMem, including the mem_info structure
+
+ @Input psMemInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psMemInfo)
@@ -850,22 +1008,13 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVFreeDeviceMemKM(IMG_HANDLE hDevCookie,
return PVRSRV_ERROR_INVALID_PARAMS;
}
- // XXX do we need this?
- if (psMemInfo->psKernelSyncInfo && psMemInfo->psKernelSyncInfo->hSmartCache)
- {
- BM_UnregisterSmart(psMemInfo->sMemBlk.hBuffer,
- psMemInfo->psKernelSyncInfo->hSmartCache);
- PVRMMapFreeSmart(psMemInfo->psKernelSyncInfo->hSmartCache);
- psMemInfo->psKernelSyncInfo->hSmartCache = NULL;
- }
-
if (psMemInfo->sMemBlk.hResItem != IMG_NULL)
{
eError = ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
}
else
{
-
+ /* PVRSRV_MEM_NO_RESMAN */
eError = FreeDeviceMemCallBack(psMemInfo, 0, CLEANUP_WITH_POLL);
}
@@ -956,14 +1105,40 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapFromDevKM(IMG_HANDLE hDevCookie,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocDeviceMemKM
+
+ @Description
+
+ Allocates device memory
+
+ @Input hDevCookie :
+ @Input psPerProc : Per-process data
+ @Input hDevMemHeap
+ @Input ui32Flags : Some combination of PVRSRV_MEM_ flags
+ @Input ui32Size : Number of bytes to allocate
+ @Input ui32Alignment :
+ @Output **ppsMemInfo : On success, receives a pointer to the created MEM_INFO structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
- PVRSRV_PER_PROCESS_DATA *psPerProc,
- IMG_HANDLE hDevMemHeap,
- IMG_UINT32 ui32Flags,
- IMG_SIZE_T ui32Size,
- IMG_SIZE_T ui32Alignment,
- PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
+PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
+ PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevMemHeap,
+ IMG_UINT32 ui32Flags,
+ IMG_SIZE_T ui32Size,
+ IMG_SIZE_T ui32Alignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ PVRSRV_KERNEL_MEM_INFO **ppsMemInfo)
{
PVRSRV_KERNEL_MEM_INFO *psMemInfo;
PVRSRV_ERROR eError;
@@ -971,15 +1146,46 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext;
if (!hDevMemHeap ||
- (ui32Size == 0))
+ ((ui32Size == 0) && ((ui32Flags & PVRSRV_MEM_SPARSE) == 0)) ||
+ (((ui32ChunkSize == 0) || (ui32NumVirtChunks == 0) || (ui32NumPhysChunks == 0) ||
+ (pabMapChunk == IMG_NULL )) && (ui32Flags & PVRSRV_MEM_SPARSE)))
{
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* Sprase alloc input validation */
+ if (ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Check = 0;
+
+ if (ui32NumVirtChunks < ui32NumPhysChunks)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ for (i=0;i<ui32NumVirtChunks;i++)
+ {
+ if (pabMapChunk[i])
+ {
+ ui32Check++;
+ }
+ }
+ if (ui32NumPhysChunks != ui32Check)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ }
+
+ /* FIXME: At the moment we force CACHETYPE override allocations to
+ * be multiples of PAGE_SIZE and page aligned. If the RA/BM
+ * is fixed, this limitation can be removed.
+ *
+ * INTEGRATION_POINT: HOST_PAGESIZE() is not correct, should be device-specific.
+ */
if (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)
{
-
+ /* PRQA S 3415 1 */ /* order of evaluation is not important */
if (((ui32Size % HOST_PAGESIZE()) != 0) ||
((ui32Alignment % HOST_PAGESIZE()) != 0))
{
@@ -992,6 +1198,12 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
ui32Flags,
ui32Size,
ui32Alignment,
+ pvPrivData,
+ ui32PrivDataLength,
+ ui32ChunkSize,
+ ui32NumVirtChunks,
+ ui32NumPhysChunks,
+ pabMapChunk,
&psMemInfo);
if (eError != PVRSRV_OK)
@@ -1005,9 +1217,10 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
}
else
{
-
-
-
+ /*
+ allocate a syncinfo but don't register with resman
+ because the holding devicemem will handle the syncinfo
+ */
psBMHeap = (BM_HEAP*)hDevMemHeap;
hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
eError = PVRSRVAllocSyncInfoKM(hDevCookie,
@@ -1017,17 +1230,11 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
{
goto free_mainalloc;
}
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
-
- if (ui32Flags & PVRSRV_HAP_SMART)
- {
- psMemInfo->psKernelSyncInfo->hSmartCache = (IMG_HANDLE)
- PVRMMapAllocateSmart(psMemInfo->psKernelSyncInfo);
- BM_RegisterSmart(psMemInfo->sMemBlk.hBuffer, psMemInfo->psKernelSyncInfo->hSmartCache);
- }
}
-
+ /*
+ * Setup the output.
+ */
*ppsMemInfo = psMemInfo;
if (ui32Flags & PVRSRV_MEM_NO_RESMAN)
@@ -1036,7 +1243,7 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
}
else
{
-
+ /* register with the resman */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_ALLOCATION,
psMemInfo,
@@ -1044,27 +1251,282 @@ PVRSRV_ERROR IMG_CALLCONV _PVRSRVAllocDeviceMemKM(IMG_HANDLE hDevCookie,
&FreeDeviceMemCallBack);
if (psMemInfo->sMemBlk.hResItem == IMG_NULL)
{
-
eError = PVRSRV_ERROR_OUT_OF_MEMORY;
goto free_mainalloc;
}
}
-
- psMemInfo->ui32RefCount++;
+ /* increment the refcount */
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
psMemInfo->memType = PVRSRV_MEMTYPE_DEVICE;
-
+ /*
+ * And I think we're done for now....
+ */
return (PVRSRV_OK);
free_mainalloc:
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
FreeDeviceMem(psMemInfo);
return eError;
}
+#if defined(SUPPORT_ION)
+static PVRSRV_ERROR IonUnmapCallback(IMG_PVOID pvParam,
+ IMG_UINT32 ui32Param,
+ IMG_BOOL bDummy)
+{
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = (PVRSRV_KERNEL_MEM_INFO *)pvParam;
+
+ PVR_UNREFERENCED_PARAMETER(bDummy);
+
+ return FreeMemCallBackCommon(psMemInfo, ui32Param, PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVMapIonHandleKM
+
+ @Description
+
+ Map an ION buffer into the specified device memory context
+
+ @Input psPerProc : PerProcess data
+ @Input hDevCookie : Device node cookie
+ @Input hDevMemContext : Device memory context cookie
+ @Input hIon : Handle to ION buffer
+ @Input ui32Flags : Mapping flags
+ @Input ui32Size : Mapping size
+ @Output ppsKernelMemInfo: Output kernel meminfo if successful
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR PVRSRVMapIonHandleKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
+ IMG_HANDLE hDevCookie,
+ IMG_HANDLE hDevMemContext,
+ IMG_HANDLE hIon,
+ IMG_UINT32 ui32Flags,
+ IMG_UINT32 ui32Size,
+ PVRSRV_KERNEL_MEM_INFO **ppsKernelMemInfo)
+{
+ PVRSRV_ENV_PER_PROCESS_DATA *psPerProcEnv = PVRSRVProcessPrivateData(psPerProc);
+ PVRSRV_DEVICE_NODE *psDeviceNode;
+ PVRSRV_KERNEL_MEM_INFO *psNewKernelMemInfo;
+ DEVICE_MEMORY_INFO *psDevMemoryInfo;
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
+ IMG_SYS_PHYADDR *pasSysPhysAddr;
+ PVRSRV_MEMBLK *psMemBlock;
+ PVRSRV_ERROR eError;
+ IMG_HANDLE hDevMemHeap = IMG_NULL;
+ IMG_HANDLE hPriv;
+ BM_HANDLE hBuffer;
+ IMG_UINT32 ui32HeapCount;
+ IMG_UINT32 ui32PageCount;
+ IMG_UINT32 i;
+ IMG_BOOL bAllocSync = (ui32Flags & PVRSRV_MEM_NO_SYNCOBJ)?IMG_FALSE:IMG_TRUE;
+
+ if ((hDevCookie == IMG_NULL) || (ui32Size == 0)
+ || (hDevMemContext == IMG_NULL) || (ppsKernelMemInfo == IMG_NULL))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Invalid params", __FUNCTION__));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevCookie;
+
+ if(OSAllocMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ (IMG_VOID **)&psNewKernelMemInfo, IMG_NULL,
+ "Kernel Memory Info") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Failed to alloc memory for block", __FUNCTION__));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ OSMemSet(psNewKernelMemInfo, 0, sizeof(PVRSRV_KERNEL_MEM_INFO));
+
+ /* Choose the heap to map to */
+ ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
+ psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
+ psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
+ for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
+ {
+ if(HEAP_IDX(psDeviceMemoryHeap[i].ui32HeapID) == psDevMemoryInfo->ui32IonHeapID)
+ {
+ if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
+ {
+ if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
+ {
+ hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
+ }
+ else
+ {
+ hDevMemHeap = IMG_NULL;
+ }
+ }
+ else
+ {
+ hDevMemHeap = psDevMemoryInfo->psDeviceMemoryHeap[i].hDevMemHeap;
+ }
+ break;
+ }
+ }
+
+ if (hDevMemHeap == IMG_NULL)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get ION heap", __FUNCTION__));
+ eError = PVRSRV_ERROR_FAILED_TO_RETRIEVE_HEAPINFO;
+ goto exitFailedHeap;
+ }
+
+ /* Import the ION buffer into our ion_client and DMA map it */
+ eError = IonImportBufferAndAquirePhysAddr(psPerProcEnv->psIONClient,
+ hIon,
+ &ui32PageCount,
+ &pasSysPhysAddr,
+ &psNewKernelMemInfo->pvLinAddrKM,
+ &hPriv);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to get ion buffer/buffer phys addr", __FUNCTION__));
+ goto exitFailedHeap;
+ }
+
+ /* Wrap the returned addresses into our memory context */
+ if (!BM_Wrap(hDevMemHeap,
+ ui32Size,
+ 0,
+ IMG_FALSE,
+ pasSysPhysAddr,
+ IMG_NULL,
+ &ui32Flags, /* This function clobbers our bits in ui32Flags */
+ &hBuffer))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to wrap ion buffer", __FUNCTION__));
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exitFailedWrap;
+ }
+
+ /* Fill in "Implementation dependant" section of mem info */
+ psMemBlock = &psNewKernelMemInfo->sMemBlk;
+ psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
+ psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
+ psMemBlock->hBuffer = (IMG_HANDLE) hBuffer;
+ psMemBlock->hOSWrapMem = hPriv; /* Saves creating a new element as we know hOSWrapMem will not be used */
+ psMemBlock->psIntSysPAddr = pasSysPhysAddr;
+
+ psNewKernelMemInfo->ui32Flags = ui32Flags;
+ psNewKernelMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
+ psNewKernelMemInfo->uAllocSize = ui32Size;
+ psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_ION;
+ PVRSRVKernelMemInfoIncRef(psNewKernelMemInfo);
+
+ /* Clear the Backup buffer pointer as we do not have one at this point. We only allocate this as we are going up/down */
+ psNewKernelMemInfo->pvSysBackupBuffer = IMG_NULL;
+
+ if (!bAllocSync)
+ {
+ psNewKernelMemInfo->psKernelSyncInfo = IMG_NULL;
+ }
+ else
+ {
+ eError = PVRSRVAllocSyncInfoKM(hDevCookie,
+ hDevMemContext,
+ &psNewKernelMemInfo->psKernelSyncInfo);
+ if(eError != PVRSRV_OK)
+ {
+ goto exitFailedSync;
+ }
+ }
+
+ /* register with the resman */
+ psNewKernelMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
+ RESMAN_TYPE_DEVICEMEM_ION,
+ psNewKernelMemInfo,
+ 0,
+ &IonUnmapCallback);
+ if (psNewKernelMemInfo->sMemBlk.hResItem == IMG_NULL)
+ {
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ goto exitFailedResman;
+ }
+
+ psNewKernelMemInfo->memType = PVRSRV_MEMTYPE_ION;
+
+ *ppsKernelMemInfo = psNewKernelMemInfo;
+ return PVRSRV_OK;
+
+exitFailedResman:
+ if (psNewKernelMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psNewKernelMemInfo->psKernelSyncInfo, psNewKernelMemInfo);
+ }
+exitFailedSync:
+ BM_Free(hBuffer, ui32Flags);
+exitFailedWrap:
+ IonUnimportBufferAndReleasePhysAddr(hPriv);
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(IMG_SYS_PHYADDR) * ui32PageCount,
+ pasSysPhysAddr,
+ IMG_NULL);
+exitFailedHeap:
+ OSFreeMem(PVRSRV_PAGEABLE_SELECT,
+ sizeof(PVRSRV_KERNEL_MEM_INFO),
+ psNewKernelMemInfo,
+ IMG_NULL);
+
+ return eError;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVUnmapIonHandleKM
+
+ @Description
+
+ Frees an ion buffer mapped with PVRSRVMapIonHandleKM, including the mem_info structure
+
+ @Input psMemInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_EXPORT
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapIonHandleKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+{
+ if (!psMemInfo)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ return ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+}
+#endif /* SUPPORT_ION */
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVDissociateDeviceMemKM
+
+ @Description
+
+ Dissociates memory from the process that allocates it. Intended for
+ transfering the ownership of device memory from a particular process
+ to the kernel.
+ @Input psMemInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psMemInfo)
@@ -1087,13 +1549,34 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDissociateDeviceMemKM(IMG_HANDLE hD
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetFreeDeviceMemKM
+
+ @Description
+
+ Determines how much memory remains available in the system with the specified
+ capabilities.
+
+ @Input ui32Flags :
+
+ @Output pui32Total :
+
+ @Output pui32Free :
+
+ @Output pui32LargestBlock :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
IMG_SIZE_T *pui32Total,
IMG_SIZE_T *pui32Free,
IMG_SIZE_T *pui32LargestBlock)
{
-
+ /* TO BE IMPLEMENTED */
PVR_UNREFERENCED_PARAMETER(ui32Flags);
PVR_UNREFERENCED_PARAMETER(pui32Total);
@@ -1106,6 +1589,17 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetFreeDeviceMemKM(IMG_UINT32 ui32Flags,
+/*!
+******************************************************************************
+ @Function PVRSRVUnwrapExtMemoryKM
+
+ @Description On last unwrap of a given meminfo, unmaps physical pages from a
+ wrapped allocation, and frees the associated device address space.
+ Note: this can only unmap memory mapped by PVRSRVWrapExtMemory
+
+ @Input psMemInfo - mem info describing the wrapped allocation
+ @Return None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
@@ -1118,6 +1612,16 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVUnwrapExtMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMem
}
+/*!
+******************************************************************************
+ @Function UnwrapExtMemoryCallBack
+
+ @Description Resman callback to unwrap memory
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
@@ -1128,16 +1632,21 @@ static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
struct drm_gem_object *buf =
BM_GetGEM(psMemInfo->sMemBlk.hBuffer);
#endif
- PVRSRV_ERROR err = FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+ PVRSRV_ERROR err = FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
PVR_UNREFERENCED_PARAMETER(bDummy);
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
if (buf) {
- if (bPhysContig) {
+ if (omap_gem_flags(buf) & OMAP_BO_TILED_MASK) {
omap_gem_put_paddr(buf);
} else {
- omap_gem_put_pages(buf);
+ if (bPhysContig) {
+ omap_gem_put_paddr(buf);
+ } else {
+ omap_gem_put_pages(buf);
+ }
}
}
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
@@ -1146,6 +1655,26 @@ static PVRSRV_ERROR UnwrapExtMemoryCallBack(IMG_PVOID pvParam,
}
+/*!
+******************************************************************************
+ @Function PVRSRVWrapExtMemoryKM
+
+ @Description Allocates a Device Virtual Address in the shared mapping heap
+ and maps physical pages into that allocation. Note, if the pages are
+ already mapped into the heap, the existing allocation is returned.
+
+ @Input hDevCookie - Device cookie
+ @Input psPerProc - Per-process data
+ @Input hDevMemContext - device memory context
+ @Input uByteSize - Size of allocation
+ @Input uPageOffset - Offset into the first page of the memory to be wrapped
+ @Input bPhysContig - whether the underlying memory is physically contiguous
+ @Input psExtSysPAddr - The list of Device Physical page addresses
+ @Input pvLinAddr - ptr to buffer to wrap
+ @Output ppsMemInfo - mem info describing the wrapped allocation
+ @Return None
+******************************************************************************/
+
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
PVRSRV_PER_PROCESS_DATA *psPerProc,
@@ -1187,14 +1716,14 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
if(pvLinAddr)
{
-
+ /* derive the page offset from the cpu ptr (in case it's not supplied) */
uPageOffset = (IMG_UINTPTR_T)pvLinAddr & (ui32HostPageSize - 1);
-
+ /* get the pagecount and the page aligned base ptr */
uPageCount = HOST_PAGEALIGN(uByteSize + uPageOffset) / ui32HostPageSize;
pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvLinAddr - uPageOffset);
-
+ /* allocate array of SysPAddr to hold page addresses */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
uPageCount * sizeof(IMG_SYS_PHYADDR),
(IMG_VOID **)&psIntSysPAddr, IMG_NULL,
@@ -1211,23 +1740,20 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
if(eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVWrapExtMemoryKM: Failed to alloc memory for block"));
- eError = PVRSRV_ERROR_OUT_OF_MEMORY;
+ eError = PVRSRV_ERROR_OUT_OF_MEMORY;//FIXME: need better error code
goto ErrorExitPhase1;
}
-
+ /* replace the supplied page address list */
psExtSysPAddr = psIntSysPAddr;
-
-
+ /* assume memory is not physically contiguous;
+ we shouldn't trust what the user says here
+ */
bPhysContig = IMG_FALSE;
}
- else
- {
-
- }
-
+ /* Choose the heap to map to */
psDevMemoryInfo = &((BM_CONTEXT*)hDevMemContext)->psDeviceNode->sDevMemoryInfo;
psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
for(i=0; i<PVRSRV_MAX_CLIENT_HEAPS; i++)
@@ -1236,7 +1762,6 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
{
if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
{
-
if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
{
hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
@@ -1291,27 +1816,29 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
goto ErrorExitPhase3;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
psMemBlock->hOSWrapMem = hOSWrapMem;
psMemBlock->psIntSysPAddr = psIntSysPAddr;
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
psMemInfo->uAllocSize = uByteSize;
-
-
+ /* Clear the Backup buffer pointer as we do not have one at this point.
+ We only allocate this as we are going up/down
+ */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
-
-
+ /*
+ allocate a syncinfo but don't register with resman
+ because the holding devicemem will handle the syncinfo
+ */
psBMHeap = (BM_HEAP*)hDevMemHeap;
hDevMemContext = (IMG_HANDLE)psBMHeap->pBMContext;
eError = PVRSRVAllocSyncInfoKM(hDevCookie,
@@ -1322,34 +1849,33 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVWrapExtMemoryKM(IMG_HANDLE hDevCookie,
goto ErrorExitPhase4;
}
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
-
-
- psMemInfo->ui32RefCount++;
+ /* increment the refcount */
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
psMemInfo->memType = PVRSRV_MEMTYPE_WRAPPED;
-
+ /* Register Resource */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_WRAP,
psMemInfo,
0,
&UnwrapExtMemoryCallBack);
-
+ /* return the meminfo */
*ppsMemInfo = psMemInfo;
return PVRSRV_OK;
-
+ /* error handling: */
ErrorExitPhase4:
if(psMemInfo)
{
FreeDeviceMem(psMemInfo);
-
-
-
+ /*
+ FreeDeviceMem will free the meminfo so set
+ it to NULL to avoid double free below
+ */
psMemInfo = IMG_NULL;
}
@@ -1357,7 +1883,7 @@ ErrorExitPhase3:
if(psMemInfo)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
ErrorExitPhase2:
@@ -1370,23 +1896,47 @@ ErrorExitPhase1:
if(psIntSysPAddr)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, uPageCount * sizeof(IMG_SYS_PHYADDR), psIntSysPAddr, IMG_NULL);
-
+ /*not nulling shared pointer, uninitialized to this point*/
}
return eError;
}
+struct async_unmap_data {
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo;
+ IMG_UINT32 ui32PID;
+};
+
static void async_unmap(void *arg)
{
- PVRSRV_KERNEL_MEM_INFO *psMemInfo = arg;
+ struct async_unmap_data *data = arg;
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo = data->psMemInfo;
LinuxLockMutex(&gPVRSRVLock);
ResManFreeResByPtr(psMemInfo->sMemBlk.hResItem, CLEANUP_WITH_POLL);
+ /* decrement the refcnt on the per-proc: */
+ PVRSRVPerProcessDataDisconnect(data->ui32PID);
LinuxUnLockMutex(&gPVRSRVLock);
+
+ kfree(data);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVUnmapDeviceMemoryKM
+
+ @Description
+ Unmaps an existing allocation previously mapped by PVRSRVMapDeviceMemory
+
+ @Input psMemInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
-PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo)
+PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ PVRSRV_PER_PROCESS_DATA *psPerProc)
{
struct drm_gem_object *buf;
@@ -1398,18 +1948,20 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psM
buf = BM_GetGEM(psMemInfo->sMemBlk.hBuffer);
if (buf)
{
- // TODO: this approach will leave the buffer in the RM until
- // the sync-obj callback.. but if the process exits, then it
- // might get deleted by RM w/ blits in progress. Possibly
- // we should be doing this *after* the RM callback so it is
- // already removed from RM? OTOH, if SGX is hung and the
- // sync-objs never get updated, could that leave us with a
- // buffer that could never be free'd?
+ struct async_unmap_data *data = kmalloc(sizeof *data, GFP_KERNEL);
int ret;
+ /* need to hold a ref to the per-proc, so an exiting/crashing
+ * app while there are still pending buffers for async free
+ * doesn't trigger premature cleanup..
+ */
+ PVRSRVPerProcessDataConnect(psPerProc->ui32PID, 0);
+ data->psMemInfo = psMemInfo;
+ data->ui32PID = psPerProc->ui32PID;
+
LinuxUnLockMutex(&gPVRSRVLock);
ret = omap_gem_op_async(buf, OMAP_GEM_READ|OMAP_GEM_WRITE,
- async_unmap, psMemInfo);
+ async_unmap, data);
LinuxLockMutex(&gPVRSRVLock);
if (ret == 0)
return PVRSRV_OK;
@@ -1420,6 +1972,17 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceMemoryKM (PVRSRV_KERNEL_MEM_INFO *psM
}
+/*!
+******************************************************************************
+ @Function UnmapDeviceMemoryCallBack
+
+ @Description Resman callback to unmap memory memory previously mapped
+ from one allocation to another
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
@@ -1438,16 +2001,7 @@ static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
if( psMapData->psMemInfo->psKernelSyncInfo )
{
- psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount--;
- if (psMapData->psMemInfo->psKernelSyncInfo->ui32RefCount == 0)
- {
- eError = PVRSRVFreeSyncInfoKM(psMapData->psMemInfo->psKernelSyncInfo);
- if(eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"UnmapDeviceMemoryCallBack: Failed to free sync info"));
- return eError;
- }
- }
+ PVRSRVKernelSyncInfoDecRef(psMapData->psMemInfo->psKernelSyncInfo, psMapData->psMemInfo);
}
eError = FreeDeviceMem(psMapData->psMemInfo);
@@ -1457,16 +2011,34 @@ static PVRSRV_ERROR UnmapDeviceMemoryCallBack(IMG_PVOID pvParam,
return eError;
}
-
- eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0, IMG_FALSE);
+ /* This will only free the src psMemInfo if we hold the last reference */
+ eError = FreeMemCallBackCommon(psMapData->psSrcMemInfo, 0,
+ PVRSRV_FREE_CALLBACK_ORIGIN_IMPORTER);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVMapDeviceMemoryKM
+
+ @Description
+ Maps an existing allocation to a specific device address space and heap
+ Note: it's valid to map from one physical device to another
+
+ @Input psPerProc : Per-process data
+ @Input psSrcMemInfo
+ @Input hDstDevMemHeap
+ @Input ppsDstMemInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_KERNEL_MEM_INFO *psSrcMemInfo,
@@ -1489,24 +2061,23 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPer
IMG_VOID *pvPageAlignedCPUVAddr;
RESMAN_MAP_DEVICE_MEM_DATA *psMapData = IMG_NULL;
-
+ /* check params */
if(!psSrcMemInfo || !hDstDevMemHeap || !ppsDstMemInfo)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceMemoryKM: invalid parameters"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* initialise the Dst Meminfo to NULL*/
*ppsDstMemInfo = IMG_NULL;
uPageOffset = psSrcMemInfo->sDevVAddr.uiAddr & (ui32HostPageSize - 1);
uPageCount = HOST_PAGEALIGN(psSrcMemInfo->uAllocSize + uPageOffset) / ui32HostPageSize;
pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)psSrcMemInfo->pvLinAddrKM - uPageOffset);
-
-
-
-
+ /*
+ allocate array of SysPAddr to hold SRC allocation page addresses
+ */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
uPageCount*sizeof(IMG_SYS_PHYADDR),
(IMG_VOID **)&psSysPAddr, IMG_NULL,
@@ -1518,23 +2089,23 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPer
psBuf = psSrcMemInfo->sMemBlk.hBuffer;
-
+ /* get the device node */
psDeviceNode = psBuf->pMapping->pBMHeap->pBMContext->psDeviceNode;
-
+ /* build a list of physical page addresses */
sDevVAddr.uiAddr = psSrcMemInfo->sDevVAddr.uiAddr - IMG_CAST_TO_DEVVADDR_UINT(uPageOffset);
for(i=0; i<uPageCount; i++)
{
BM_GetPhysPageAddr(psSrcMemInfo, sDevVAddr, &sDevPAddr);
-
+ /* save the address */
psSysPAddr[i] = SysDevPAddrToSysPAddr (psDeviceNode->sDevId.eDeviceType, sDevPAddr);
-
+ /* advance the DevVaddr one page */
sDevVAddr.uiAddr += IMG_CAST_TO_DEVVADDR_UINT(ui32HostPageSize);
}
-
+ /* allocate the resman map data */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(RESMAN_MAP_DEVICE_MEM_DATA),
(IMG_VOID **)&psMapData, IMG_NULL,
@@ -1576,50 +2147,51 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPer
goto ErrorExit;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
+ /* Store page list */
psMemBlock->psIntSysPAddr = psSysPAddr;
-
+ /* patch up the CPU VAddr into the meminfo */
psMemInfo->pvLinAddrKM = psSrcMemInfo->pvLinAddrKM;
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
psMemInfo->uAllocSize = psSrcMemInfo->uAllocSize;
psMemInfo->psKernelSyncInfo = psSrcMemInfo->psKernelSyncInfo;
-
+ /* reference the same ksi that the original meminfo referenced */
if(psMemInfo->psKernelSyncInfo)
{
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
}
-
-
+ /* Clear the Backup buffer pointer as we do not have one at this point.
+ We only allocate this as we are going up/down
+ */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
- psMemInfo->ui32RefCount++;
+ /* increment our refcount */
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
-
- psSrcMemInfo->ui32RefCount++;
+ /* increment the src refcount */
+ PVRSRVKernelMemInfoIncRef(psSrcMemInfo);
-
+ /* Tell the buffer manager about the export */
BM_Export(psSrcMemInfo->sMemBlk.hBuffer);
psMemInfo->memType = PVRSRV_MEMTYPE_MAPPED;
-
+ /* setup the resman map data */
psMapData->psMemInfo = psMemInfo;
psMapData->psSrcMemInfo = psSrcMemInfo;
-
+ /* Register Resource */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICEMEM_MAPPING,
psMapData,
@@ -1630,29 +2202,29 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceMemoryKM(PVRSRV_PER_PROCESS_DATA *psPer
return PVRSRV_OK;
-
+ /* error handling: */
ErrorExit:
if(psSysPAddr)
{
-
+ /* Free the page address list */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(IMG_SYS_PHYADDR), psSysPAddr, IMG_NULL);
-
+ /*not nulling shared pointer, holding structure could be not initialized*/
}
if(psMemInfo)
{
-
+ /* Free the page address list */
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(PVRSRV_KERNEL_MEM_INFO), psMemInfo, IMG_NULL);
-
+ /*not nulling shared pointer, holding structure could be not initialized*/
}
if(psMapData)
{
-
+ /* Free the resman map data */
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(RESMAN_MAP_DEVICE_MEM_DATA), psMapData, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
}
return eError;
@@ -1672,13 +2244,21 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVImportGEMKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_MEMBLK *psMemBlock;
IMG_BOOL bBMError;
PVRSRV_ERROR eError;
- IMG_UINT32 i;
- IMG_SIZE_T uByteSize;
+ IMG_UINT32 i;
+ IMG_UINT32 j;
+ IMG_SIZE_T uByteSize = 0;
IMG_SIZE_T uPageOffset;
+ IMG_SIZE_T uTilerStride = 0;
+ IMG_UINT32 uTilerBPP = 0;
+ IMG_SIZE_T uPagesPerRow = 0;
+ IMG_UINT16 uTiledBufWidth;
+ IMG_UINT16 uTiledBufHeight;
IMG_BOOL bPhysContig;
- IMG_SYS_PHYADDR *psSysPAddr; /* array of page addresses */
+ IMG_SYS_PHYADDR *psSysPAddr; /* array of page addresses */
IMG_UINT32 ui32Flags;
- IMG_SIZE_T uPageCount = 0;
+ IMG_SIZE_T uPageCount = 0;
+ dma_addr_t paddr = 0;
+ struct page **pages = NULL;
PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc =
(PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
struct drm_gem_object *buf =
@@ -1707,15 +2287,43 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVImportGEMKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
if (omap_gem_flags(buf) & OMAP_BO_TILED_MASK)
{
- // TODO
- PVR_DPF((PVR_DBG_ERROR,"PVRSRVImportGEMKM: not implemented"));
- return PVRSRV_ERROR_INVALID_PARAMS;
+ if (!omap_gem_get_paddr(buf, &paddr, true))
+ {
+ if (omap_gem_tiled_size(buf, &uTiledBufWidth, &uTiledBufHeight))
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVImportGEMKM: Failed to get TILED buffer size. Maybe buf is not tiled after all ?"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ switch (omap_gem_flags(buf) & OMAP_BO_TILED_MASK) {
+ case OMAP_BO_TILED_8:
+ uTilerBPP = 1;
+ break;
+ case OMAP_BO_TILED_16:
+ uTilerBPP = 2;
+ break;
+ case OMAP_BO_TILED_32:
+ uTilerBPP = 4;
+ break;
+ default:
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVImportGEMKM: Wrong GEM bo format for rotation !"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ uPageOffset = paddr & (ui32HostPageSize - 1);
+ paddr &= ~(ui32HostPageSize - 1);
+ bPhysContig = IMG_FALSE;
+ uTilerStride = omap_gem_tiled_stride(buf, 0);
+ uPagesPerRow = ((uTiledBufWidth * uTilerBPP) / PAGE_SIZE) + 1;
+ uPageCount = uPagesPerRow * uTiledBufHeight;
+ uByteSize = buf->size;
+ }
+ else
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVImportGEMKM: Failed to get paddr of TILED buffer"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
}
else
{
- dma_addr_t paddr = 0;
- struct page **pages = NULL;
-
if (!omap_gem_get_paddr(buf, &paddr, false))
{
uPageOffset = paddr & (ui32HostPageSize - 1);
@@ -1735,19 +2343,32 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVImportGEMKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
uByteSize = buf->size;
uPageCount = HOST_PAGEALIGN(uByteSize + uPageOffset) / ui32HostPageSize;
+ }
- PVR_DPF((PVR_DBG_MESSAGE,"paddr=%08x, pages=%p, uByteSize=%d, uPageCount=%d",
- (u32)paddr, pages, uByteSize, uPageCount));
+ PVR_DPF((PVR_DBG_MESSAGE,"paddr=%08x, pages=%p, uByteSize=%d, uPageCount=%d",
+ (u32)paddr, pages, uByteSize, uPageCount));
- if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
- uPageCount * sizeof(IMG_SYS_PHYADDR),
- (IMG_VOID **)&psSysPAddr, IMG_NULL,
- "Array of Page Addresses") != PVRSRV_OK)
+ if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
+ uPageCount * sizeof(IMG_SYS_PHYADDR),
+ (IMG_VOID **)&psSysPAddr, IMG_NULL,
+ "Array of Page Addresses") != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVImportGEMKM: Failed to alloc memory for block"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ if (omap_gem_flags(buf) & OMAP_BO_TILED_MASK)
+ {
+ for (i = 0; i < uTiledBufHeight; i++)
{
- PVR_DPF((PVR_DBG_ERROR,"PVRSRVImportGEMKM: Failed to alloc memory for block"));
- return PVRSRV_ERROR_OUT_OF_MEMORY;
+ for (j = 0; j < uPagesPerRow; j++)
+ {
+ psSysPAddr[(i * uPagesPerRow) + j].uiAddr = paddr + (i * uTilerStride) + (j * PAGE_SIZE);
+ }
}
-
+ }
+ else
+ {
if (bPhysContig)
{
for (i = 0; i < uPageCount; i++)
@@ -1834,9 +2455,10 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVImportGEMKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
omap_gem_set_sync_object(buf, psMemInfo->psKernelSyncInfo->psSyncData);
}
-
- psMemInfo->psKernelSyncInfo->ui32RefCount++;
-
+ else
+ {
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
psMemInfo->ui32RefCount++;
@@ -1890,7 +2512,19 @@ ErrorExitPhase2:
}
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
+/*!
+******************************************************************************
+ @Function PVRSRVUnmapDeviceClassMemoryKM
+ @Description unmaps physical pages from devices address space at a specified
+ Device Virtual Address.
+ Note: this can only unmap memory mapped by
+ PVRSRVMapDeviceClassMemoryKM
+
+ @Input psMemInfo - mem info describing the device virtual address
+ to unmap RAM from
+ @Return None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo)
{
@@ -1903,6 +2537,16 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVUnmapDeviceClassMemoryKM(PVRSRV_KERNEL_MEM_INFO
}
+/*!
+******************************************************************************
+ @Function UnmapDeviceClassMemoryCallBack
+
+ @Description Resman callback to unmap device class memory
+
+ @Input pvParam - opaque void ptr param
+ @Input ui32Param - opaque unsigned long param
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID pvParam,
IMG_UINT32 ui32Param,
IMG_BOOL bDummy)
@@ -1932,10 +2576,28 @@ static PVRSRV_ERROR UnmapDeviceClassMemoryCallBack(IMG_PVOID pvParam,
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_DC_MAPINFO), psDCMapInfo, IMG_NULL);
- return FreeMemCallBackCommon(psMemInfo, ui32Param, IMG_TRUE);
+ return FreeMemCallBackCommon(psMemInfo, ui32Param,
+ PVRSRV_FREE_CALLBACK_ORIGIN_ALLOCATOR);
}
+/*!
+******************************************************************************
+ @Function PVRSRVMapDeviceClassMemoryKM
+
+ @Description maps physical pages for DeviceClass buffers into a devices
+ address space at a specified and pre-allocated Device
+ Virtual Address
+
+ @Input psPerProc - Per-process data
+ @Input hDevMemContext - Device memory context
+ @Input hDeviceClassBuffer - Device Class Buffer (Surface) handle
+ @Input hDevMemContext - device memory context to which mapping
+ is made
+ @Output ppsMemInfo - mem info describing the mapped memory
+ @Output phOSMapInfo - OS specific mapping information
+ @Return None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevMemContext,
@@ -1969,7 +2631,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* allocate resman storage structure */
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_DC_MAPINFO),
(IMG_VOID **)&psDCMapInfo, IMG_NULL,
@@ -1982,25 +2644,26 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
psDeviceClassBuffer = (PVRSRV_DEVICECLASS_BUFFER*)hDeviceClassBuffer;
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ /*
+ call into external driver to get info so we can map a meminfo
+ Notes:
+ It's expected that third party displays will only support
+ physically contiguous display surfaces. However, it's possible
+ a given display may have an MMU and therefore support non-contig'
+ display surfaces.
+
+ If surfaces are contiguous, ext driver should return:
+ - a CPU virtual address, or IMG_NULL where the surface is not mapped to CPU
+ - (optional) an OS Mapping handle for KM->UM surface mapping
+ - the size in bytes
+ - a single system physical address
+
+ If surfaces are non-contiguous, ext driver should return:
+ - a CPU virtual address
+ - (optional) an OS Mapping handle for KM->UM surface mapping
+ - the size in bytes (must be multiple of 4kB)
+ - a list of system physical addresses (at 4kB intervals)
+ */
eError = psDeviceClassBuffer->pfnGetBufferAddr(psDeviceClassBuffer->hExtDevice,
psDeviceClassBuffer->hExtBuffer,
&psSysPAddr,
@@ -2015,7 +2678,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
goto ErrorExitPhase1;
}
-
+ /* Choose the heap to map to */
psBMContext = (BM_CONTEXT*)psDeviceClassBuffer->hDevMemContext;
psDeviceNode = psBMContext->psDeviceNode;
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
@@ -2026,7 +2689,6 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
{
if(psDeviceMemoryHeap[i].DevMemHeapType == DEVICE_MEMORY_HEAP_PERCONTEXT)
{
-
if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
{
hDevMemHeap = BM_CreateHeap(hDevMemContext, &psDeviceMemoryHeap[i]);
@@ -2051,7 +2713,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
goto ErrorExitPhase1;
}
-
+ /* Only need lower 12 bits of the cpu addr - don't care what size a void* is */
ui32Offset = ((IMG_UINTPTR_T)pvCPUVAddr) & (ui32PageSize - 1);
pvPageAlignedCPUVAddr = (IMG_VOID *)((IMG_UINTPTR_T)pvCPUVAddr - ui32Offset);
@@ -2081,32 +2743,40 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
if (!bBMError)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVMapDeviceClassMemoryKM: BM_Wrap Failed"));
-
+ /*not nulling pointer, out of scope*/
eError = PVRSRV_ERROR_BAD_MAPPING;
goto ErrorExitPhase2;
}
-
+ /* Fill in "Implementation dependant" section of mem info */
psMemBlock->sDevVirtAddr = BM_HandleToDevVaddr(hBuffer);
psMemBlock->hOSMemHandle = BM_HandleToOSMemHandle(hBuffer);
-
+ /* Convert from BM_HANDLE to external IMG_HANDLE */
psMemBlock->hBuffer = (IMG_HANDLE)hBuffer;
-
-
+ /* patch up the CPU VAddr into the meminfo - use the address from the BM, not the one from the deviceclass
+ api, to ensure user mode mapping is possible
+ */
psMemInfo->pvLinAddrKM = BM_HandleToCpuVaddr(hBuffer);
-
+ /* Fill in the public fields of the MEM_INFO structure */
psMemInfo->sDevVAddr = psMemBlock->sDevVirtAddr;
psMemInfo->uAllocSize = uByteSize;
psMemInfo->psKernelSyncInfo = psDeviceClassBuffer->psKernelSyncInfo;
-
+ PVR_ASSERT(psMemInfo->psKernelSyncInfo != IMG_NULL);
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoIncRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+ /* Clear the Backup buffer pointer as we do not have one at this point.
+ We only allocate this as we are going up/down
+ */
psMemInfo->pvSysBackupBuffer = IMG_NULL;
-
+ /* setup DCMapInfo */
psDCMapInfo->psMemInfo = psMemInfo;
psDCMapInfo->psDeviceClassBuffer = psDeviceClassBuffer;
@@ -2115,7 +2785,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
if(psDCMapInfo->ui32TilingStride > 0)
{
-
+ /* try to acquire a tiling range on this device */
eError = psDeviceNode->pfnAllocMemTilingRange(psDeviceNode,
psMemInfo,
psDCMapInfo->ui32TilingStride,
@@ -2128,7 +2798,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
}
#endif
-
+ /* Register Resource */
psMemInfo->sMemBlk.hResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
psDCMapInfo,
@@ -2136,17 +2806,30 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
&UnmapDeviceClassMemoryCallBack);
(psDeviceClassBuffer->ui32MemMapRefCount)++;
- psMemInfo->ui32RefCount++;
+ PVRSRVKernelMemInfoIncRef(psMemInfo);
psMemInfo->memType = PVRSRV_MEMTYPE_DEVICECLASS;
-
+ /* return the meminfo */
*ppsMemInfo = psMemInfo;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
- PDUMPCOMMENT("Dump display surface");
- PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->uAllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+ /* If the 3PDD supplies a kernel virtual address, we can PDUMP it */
+ if(psMemInfo->pvLinAddrKM)
+ {
+ /* FIXME:
+ * Initialise the display surface here when it is mapped into Services.
+ * Otherwise there is a risk that pdump toolchain will assign previously
+ * used physical pages, leading to visual artefacts on the unrendered surface
+ * (e.g. during LLS rendering).
+ *
+ * A better method is to pdump the allocation from the DC driver, so the
+ * BM_Wrap pdumps only the virtual memory which better represents the driver
+ * behaviour.
+ */
+ PDUMPCOMMENT("Dump display surface");
+ PDUMPMEM(IMG_NULL, psMemInfo, ui32Offset, psMemInfo->uAllocSize, PDUMP_FLAGS_CONTINUOUS, ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping);
+ }
#endif
return PVRSRV_OK;
@@ -2154,10 +2837,16 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVMapDeviceClassMemoryKM(PVRSRV_PER_PROCESS_DATA *
ErrorExitPhase3:
if(psMemInfo)
{
- FreeDeviceMem(psMemInfo);
-
-
+ if (psMemInfo->psKernelSyncInfo)
+ {
+ PVRSRVKernelSyncInfoDecRef(psMemInfo->psKernelSyncInfo, psMemInfo);
+ }
+ FreeDeviceMem(psMemInfo);
+ /*
+ FreeDeviceMem will free the meminfo so set
+ it to NULL to avoid double free below
+ */
psMemInfo = IMG_NULL;
}
#endif
@@ -2203,3 +2892,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVChangeDeviceMemoryAttributesKM(IMG_HANDLE hKerne
}
+/******************************************************************************
+ End of file (devicemem.c)
+******************************************************************************/
+
diff --git a/sgx/services4/srvkm/common/handle.c b/sgx/services4/srvkm/common/handle.c
index 80f6d97..f71e67b 100644
--- a/sgx/services4/srvkm/common/handle.c
+++ b/sgx/services4/srvkm/common/handle.c
@@ -1,30 +1,61 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Handle Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource handle management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)
+/* See handle.h for a description of the handle API. */
+
+/*
+ * There is no locking here. It is assumed the code is used in a single
+ * threaded environment. In particular, it is assumed that the code will
+ * never be called from an interrupt handler.
+ *
+ * The implmentation supports movable handle structures, allowing the address
+ * of a handle structure to change without having to fix up pointers in
+ * any of the handle structures. For example, the linked list mechanism
+ * used to link subhandles together uses handle array indices rather than
+ * pointers to the structures themselves.
+ */
+
#include <stddef.h>
#include "services_headers.h"
@@ -47,6 +78,7 @@
#define INDEX_IS_VALID(psBase, i) ((i) < (psBase)->ui32TotalHandCount)
+/* Valid handles are never NULL, but handle array indices are based from 0 */
#if defined (SUPPORT_SID_INTERFACE)
#define INDEX_TO_HANDLE(i) ((IMG_SID)((i) + 1))
#define HANDLE_TO_INDEX(h) ((IMG_UINT32)(h) - 1)
@@ -110,6 +142,11 @@
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+/*
+ * Linked list structure. Used for both the list head and list items.
+ * Array indices, rather than pointers, are used to point to the next and
+ * previous items on the list.
+ */
struct sHandleList
{
IMG_UINT32 ui32Prev;
@@ -128,101 +165,162 @@ enum ePVRSRVInternalHandleFlag
INTERNAL_HANDLE_FLAG_BATCHED_PARTIALLY_FREE = 0x02,
};
+/* Handle structure */
struct sHandle
{
-
+ /* Handle type */
PVRSRV_HANDLE_TYPE eType;
-
+ /* Pointer to the data that the handle represents */
IMG_VOID *pvData;
-
+ /*
+ * When handles are on the free list, the value of the "next index
+ * plus one field" has the following meaning:
+ * zero - next handle is the one that follows this one,
+ * nonzero - the index of the next handle is the value minus one.
+ * This scheme means handle space can be initialised to all zeros.
+ *
+ * When this field is used to link together handles on a list
+ * other than the free list, zero indicates the end of the
+ * list, with nonzero the same as above.
+ */
IMG_UINT32 ui32NextIndexPlusOne;
-
+ /* Internal flags */
enum ePVRSRVInternalHandleFlag eInternalFlag;
-
+ /* Flags specified when the handle was allocated */
PVRSRV_HANDLE_ALLOC_FLAG eFlag;
-
+ /* Index of this handle in the handle array */
IMG_UINT32 ui32Index;
-
+ /* List head for subhandles of this handle */
struct sHandleList sChildren;
-
+ /* List entry for sibling subhandles */
struct sHandleList sSiblings;
};
+/* Handle array index structure.
+ * The handle array is an array of index structures, reallocated as the number of
+ * handles increases.
+ * NOTE: There is one index structure per block of handles.
+ */
struct sHandleIndex
{
-
+ /* Pointer to first handle structure in the block */
struct sHandle *psHandle;
-
+ /* Block allocation cookie returned from OSAllocMem for the block of handles */
IMG_HANDLE hBlockAlloc;
-
+ /* Number of free handles in block */
IMG_UINT32 ui32FreeHandBlockCount;
};
struct _PVRSRV_HANDLE_BASE_
{
-
+ /* Handle returned from OSAllocMem for handle base allocation */
IMG_HANDLE hBaseBlockAlloc;
-
+ /* Handle returned from OSAllocMem for handle array allocation */
IMG_HANDLE hArrayBlockAlloc;
-
+ /* Pointer to array of pointers to handle structures */
struct sHandleIndex *psHandleArray;
-
+ /*
+ * Pointer to handle hash table.
+ * The hash table is used to do reverse lookups, converting data
+ * pointers to handles.
+ */
HASH_TABLE *psHashTab;
-
+ /* Number of free handles */
IMG_UINT32 ui32FreeHandCount;
-
+ /*
+ * If purging is not enabled, this is the array index of first free
+ * handle.
+ * If purging is enabled, this is the index to start searching for
+ * a free handle from. In this case it is usually zero, unless
+ * the handle array size has been increased due to lack of
+ * handles.
+ */
IMG_UINT32 ui32FirstFreeIndex;
-
+ /* Maximum handle index, plus one */
IMG_UINT32 ui32MaxIndexPlusOne;
-
+ /* Total number of handles, free and allocated */
IMG_UINT32 ui32TotalHandCount;
-
+ /*
+ * Index of the last free index, plus one. Not used if purging
+ * is enabled.
+ */
IMG_UINT32 ui32LastFreeIndexPlusOne;
-
+ /* Size of current handle batch, or zero if batching not enabled */
IMG_UINT32 ui32HandBatchSize;
-
+ /* Number of handles prior to start of current batch */
IMG_UINT32 ui32TotalHandCountPreBatch;
-
+ /* Index of first handle in batch, plus one */
IMG_UINT32 ui32FirstBatchIndexPlusOne;
-
+ /* Number of handle allocation failures in batch */
IMG_UINT32 ui32BatchHandAllocFailures;
-
+ /* Purging enabled.
+ * If purging is enabled, the size of the table can be reduced
+ * by removing free space at the end of the table. To make
+ * purging more likely to succeed, handles are allocated as
+ * far to the front of the table as possible. The first free
+ * handle is found by a linear search from the start of the table,
+ * and so no free handle list management is done.
+ */
IMG_BOOL bPurgingEnabled;
};
+/*
+ * The key for the handle hash table is an array of three elements, the
+ * pointer to the resource, the resource type, and the process ID. The
+ * eHandKey enumeration gives the array indices of the elements making
+ * up the key.
+ */
enum eHandKey {
HAND_KEY_DATA = 0,
HAND_KEY_TYPE,
HAND_KEY_PARENT,
- HAND_KEY_LEN
+ HAND_KEY_LEN /* Must be last item in list */
};
+/*
+ * Kernel handle base structure. For handles that are not allocated on
+ * behalf of a particular process
+ */
PVRSRV_HANDLE_BASE *gpsKernelHandleBase = IMG_NULL;
+/* HAND_KEY is the type of the hash table key */
typedef IMG_UINTPTR_T HAND_KEY[HAND_KEY_LEN];
+/*!
+******************************************************************************
+
+ @Function HandleListInit
+
+ @Description Initialise a linked list structure embedded in a handle
+ structure.
+
+ @Input ui32Index - index of handle in the handle array
+ psList - pointer to linked list structure
+ hParent - parent handle, or IMG_NULL
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListInit)
#endif
@@ -238,6 +336,17 @@ IMG_VOID HandleListInit(IMG_UINT32 ui32Index, struct sHandleList *psList, IMG_HA
psList->hParent = hParent;
}
+/*!
+******************************************************************************
+
+ @Function InitParentList
+
+ @Description Initialise the children list head in a handle structure.
+ The children are the subhandles of this handle.
+
+ @Input psHandle - pointer to handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(InitParentList)
#endif
@@ -249,6 +358,18 @@ IMG_VOID InitParentList(struct sHandle *psHandle)
HandleListInit(ui32Parent, &psHandle->sChildren, INDEX_TO_HANDLE(ui32Parent));
}
+/*!
+******************************************************************************
+
+ @Function InitChildEntry
+
+ @Description Initialise the child list entry in a handle structure.
+ The list entry is used to link together subhandles of
+ a given handle.
+
+ @Input psHandle - pointer to handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(InitChildEntry)
#endif
@@ -258,6 +379,19 @@ IMG_VOID InitChildEntry(struct sHandle *psHandle)
HandleListInit(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, IMG_NULL);
}
+/*!
+******************************************************************************
+
+ @Function HandleListIsEmpty
+
+ @Description Determine whether a given linked list is empty.
+
+ @Input ui32Index - index of the handle containing the list head
+ psList - pointer to the list head
+
+ @Return IMG_TRUE if the list is empty, IMG_FALSE if it isn't.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListIsEmpty)
#endif
@@ -273,7 +407,7 @@ IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
IMG_BOOL bIsEmpty2;
bIsEmpty2 = (IMG_BOOL)(psList->ui32Prev == ui32Index);
- PVR_ASSERT(bIsEmpty == bIsEmpty2)
+ PVR_ASSERT(bIsEmpty == bIsEmpty2);
}
#endif
@@ -281,17 +415,41 @@ IMG_BOOL HandleListIsEmpty(IMG_UINT32 ui32Index, struct sHandleList *psList)
}
#ifdef DEBUG
+/*!
+******************************************************************************
+
+ @Function NoChildren
+
+ @Description Determine whether a handle has any subhandles
+
+ @Input psHandle - pointer to handle structure
+
+ @Return IMG_TRUE if the handle has no subhandles, IMG_FALSE if it does.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(NoChildren)
#endif
static INLINE
IMG_BOOL NoChildren(struct sHandle *psHandle)
{
- PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle))
+ PVR_ASSERT(psHandle->sChildren.hParent == HANDLE_PTR_TO_HANDLE(psHandle));
return HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sChildren);
}
+/*!
+******************************************************************************
+
+ @Function NoParent
+
+ @Description Determine whether a handle is a subhandle
+
+ @Input psHandle - pointer to handle structure
+
+ @Return IMG_TRUE if the handle is not a subhandle, IMG_FALSE if it is.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(NoParent)
#endif
@@ -300,17 +458,29 @@ IMG_BOOL NoParent(struct sHandle *psHandle)
{
if (HandleListIsEmpty(HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings))
{
- PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL)
+ PVR_ASSERT(psHandle->sSiblings.hParent == IMG_NULL);
return IMG_TRUE;
}
else
{
- PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL)
+ PVR_ASSERT(psHandle->sSiblings.hParent != IMG_NULL);
}
return IMG_FALSE;
}
-#endif
+#endif /*DEBUG*/
+/*!
+******************************************************************************
+
+ @Function ParentHandle
+
+ @Description Determine the parent of a handle
+
+ @Input psHandle - pointer to handle structure
+
+ @Return Parent handle, or IMG_NULL if the handle is not a subhandle.
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(ParentHandle)
#endif
@@ -324,21 +494,49 @@ IMG_HANDLE ParentHandle(struct sHandle *psHandle)
return psHandle->sSiblings.hParent;
}
+/*
+ * The LIST_PTR_FROM_INDEX_AND_OFFSET macro is used to generate either a
+ * pointer to the subhandle list head, or a pointer to the linked list
+ * structure of an item on a subhandle list.
+ * The list head is itself on the list, but is at a different offset
+ * in the handle structure to the linked list structure for items on
+ * the list. The two linked list structures are differentiated by
+ * the third parameter, containing the parent index. The parent field
+ * in the list head structure references the handle structure that contains
+ * it. For items on the list, the parent field in the linked list structure
+ * references the parent handle, which will be different from the handle
+ * containing the linked list structure.
+ */
#define LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, i, p, po, eo) \
((struct sHandleList *)((IMG_CHAR *)(INDEX_TO_HANDLE_STRUCT_PTR(psBase, i)) + (((i) == (p)) ? (po) : (eo))))
+/*!
+******************************************************************************
+
+ @Function HandleListInsertBefore
+
+ @Description Insert a handle before a handle currently on the list.
+
+ @Input ui32InsIndex - index of handle to be inserted after
+ psIns - pointer to handle structure to be inserted after
+ uiParentOffset - offset to list head struct in handle structure
+ ui32EntryIndex - index of handle to be inserted
+ psEntry - pointer to handle structure of item to be inserted
+ uiEntryOffset - offset of list item struct in handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListInsertBefore)
#endif
static INLINE
IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIndex, struct sHandleList *psIns, IMG_SIZE_T uiParentOffset, IMG_UINT32 ui32EntryIndex, struct sHandleList *psEntry, IMG_SIZE_T uiEntryOffset, IMG_UINT32 ui32ParentIndex)
{
-
+ /* PRQA S 3305 7 */ /*override stricter alignment warning */
struct sHandleList *psPrevIns = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psIns->ui32Prev, ui32ParentIndex, uiParentOffset, uiEntryOffset);
- PVR_ASSERT(psEntry->hParent == IMG_NULL)
- PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next)
- PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex))
+ PVR_ASSERT(psEntry->hParent == IMG_NULL);
+ PVR_ASSERT(ui32InsIndex == psPrevIns->ui32Next);
+ PVR_ASSERT(LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32ParentIndex, ui32ParentIndex, uiParentOffset, uiParentOffset)->hParent == INDEX_TO_HANDLE(ui32ParentIndex));
psEntry->ui32Prev = psIns->ui32Prev;
psIns->ui32Prev = ui32EntryIndex;
@@ -348,6 +546,17 @@ IMG_VOID HandleListInsertBefore(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32InsIn
psEntry->hParent = INDEX_TO_HANDLE(ui32ParentIndex);
}
+/*!
+******************************************************************************
+
+ @Function AdoptChild
+
+ @Description Assign a subhandle to a handle
+
+ @Input psParent - pointer to handle structure of parent handle
+ psChild - pointer to handle structure of child subhandle
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(AdoptChild)
#endif
@@ -356,12 +565,25 @@ IMG_VOID AdoptChild(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psParent, struct
{
IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psParent->sChildren.hParent);
- PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent))
+ PVR_ASSERT(ui32Parent == HANDLE_PTR_TO_INDEX(psParent));
HandleListInsertBefore(psBase, ui32Parent, &psParent->sChildren, offsetof(struct sHandle, sChildren), HANDLE_PTR_TO_INDEX(psChild), &psChild->sSiblings, offsetof(struct sHandle, sSiblings), ui32Parent);
}
+/*!
+******************************************************************************
+
+ @Function HandleListRemove
+
+ @Description Remove a handle from a list
+
+ @Input ui32EntryIndex - index of handle to be removed
+ psEntry - pointer to handle structure of item to be removed
+ uiEntryOffset - offset of list item struct in handle structure
+ uiParentOffset - offset to list head struct in handle structure
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListRemove)
#endif
@@ -370,12 +592,15 @@ IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex,
{
if (!HandleListIsEmpty(ui32EntryIndex, psEntry))
{
-
+ /* PRQA S 3305 3 */ /*override stricter alignment warning */
struct sHandleList *psPrev = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Prev, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
struct sHandleList *psNext = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, psEntry->ui32Next, HANDLE_TO_INDEX(psEntry->hParent), uiParentOffset, uiEntryOffset);
-
- PVR_ASSERT(psEntry->hParent != IMG_NULL)
+ /*
+ * The list head is on the list, and we don't want to
+ * remove it.
+ */
+ PVR_ASSERT(psEntry->hParent != IMG_NULL);
psPrev->ui32Next = psEntry->ui32Next;
psNext->ui32Prev = psEntry->ui32Prev;
@@ -384,6 +609,16 @@ IMG_VOID HandleListRemove(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32EntryIndex,
}
}
+/*!
+******************************************************************************
+
+ @Function UnlinkFromParent
+
+ @Description Remove a subhandle from its parents list
+
+ @Input psHandle - pointer to handle structure of child subhandle
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(UnlinkFromParent)
#endif
@@ -393,6 +628,19 @@ IMG_VOID UnlinkFromParent(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
HandleListRemove(psBase, HANDLE_PTR_TO_INDEX(psHandle), &psHandle->sSiblings, offsetof(struct sHandle, sSiblings), offsetof(struct sHandle, sChildren));
}
+/*!
+******************************************************************************
+
+ @Function HandleListIterate
+
+ @Description Iterate over the items in a list
+
+ @Input psHead - pointer to list head
+ uiParentOffset - offset to list head struct in handle structure
+ uiEntryOffset - offset of list item struct in handle structure
+ pfnIterFunc - function to be called for each handle in the list
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(HandleListIterate)
#endif
@@ -402,18 +650,24 @@ PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *p
IMG_UINT32 ui32Index;
IMG_UINT32 ui32Parent = HANDLE_TO_INDEX(psHead->hParent);
- PVR_ASSERT(psHead->hParent != IMG_NULL)
+ PVR_ASSERT(psHead->hParent != IMG_NULL);
-
+ /*
+ * Follow the next chain from the list head until we reach
+ * the list head again, which signifies the end of the list.
+ */
for(ui32Index = psHead->ui32Next; ui32Index != ui32Parent; )
{
struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32Index);
-
+ /* PRQA S 3305 2 */ /*override stricter alignment warning */
struct sHandleList *psEntry = LIST_PTR_FROM_INDEX_AND_OFFSET(psBase, ui32Index, ui32Parent, uiParentOffset, uiEntryOffset);
PVRSRV_ERROR eError;
- PVR_ASSERT(psEntry->hParent == psHead->hParent)
-
+ PVR_ASSERT(psEntry->hParent == psHead->hParent);
+ /*
+ * Get the next index now, in case the list item is
+ * modified by the iteration function.
+ */
ui32Index = psEntry->ui32Next;
eError = (*pfnIterFunc)(psBase, psHandle);
@@ -426,6 +680,17 @@ PVRSRV_ERROR HandleListIterate(PVRSRV_HANDLE_BASE *psBase, struct sHandleList *p
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function IterateOverChildren
+
+ @Description Iterate over the subhandles of a parent handle
+
+ @Input psParent - pointer to parent handle structure
+ pfnIterFunc - function to be called for each subhandle
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(IterateOverChildren)
#endif
@@ -435,6 +700,24 @@ PVRSRV_ERROR IterateOverChildren(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psP
return HandleListIterate(psBase, &psParent->sChildren, offsetof(struct sHandle, sChildren), offsetof(struct sHandle, sSiblings), pfnIterFunc);
}
+/*!
+******************************************************************************
+
+ @Function GetHandleStructure
+
+ @Description Get the handle structure for a given handle
+
+ @Input psBase - pointer to handle base structure
+ ppsHandle - location to return pointer to handle structure
+ hHandle - handle from client
+ eType - handle type or PVRSRV_HANDLE_TYPE_NONE if the
+ handle type is not to be checked.
+
+ @Output ppsHandle - points to a pointer to the handle structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(GetHandleStructure)
#endif
@@ -448,7 +731,7 @@ PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **pps
IMG_UINT32 ui32Index = HANDLE_TO_INDEX(hHandle);
struct sHandle *psHandle;
-
+ /* Check handle index is in range */
if (!INDEX_IS_VALID(psBase, ui32Index))
{
PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle index out of range (%u >= %u)", ui32Index, psBase->ui32TotalHandCount));
@@ -468,7 +751,10 @@ PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **pps
return PVRSRV_ERROR_HANDLE_NOT_ALLOCATED;
}
-
+ /*
+ * Unless PVRSRV_HANDLE_TYPE_NONE was passed in to this function,
+ * check handle is of the correct type.
+ */
if (eType != PVRSRV_HANDLE_TYPE_NONE && eType != psHandle->eType)
{
PVR_DPF((PVR_DBG_ERROR, "GetHandleStructure: Handle type mismatch (%d != %d)", eType, psHandle->eType));
@@ -478,12 +764,26 @@ PVRSRV_ERROR GetHandleStructure(PVRSRV_HANDLE_BASE *psBase, struct sHandle **pps
return PVRSRV_ERROR_HANDLE_TYPE_MISMATCH;
}
-
+ /* Return the handle structure */
*ppsHandle = psHandle;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function ParentIfPrivate
+
+ @Description Return the parent handle if the handle was allocated
+ with PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE, else return
+ IMG_NULL
+
+ @Input psHandle - pointer to handle
+
+ @Return Parent handle, or IMG_NULL
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(ParentIfPrivate)
#endif
@@ -498,6 +798,19 @@ IMG_HANDLE ParentIfPrivate(struct sHandle *psHandle)
ParentHandle(psHandle) : IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function InitKey
+
+ @Description Initialise a hash table key for the current process
+
+ @Input psBase - pointer to handle base structure
+ aKey - pointer to key
+ pvData - pointer to the resource the handle represents
+ eType - type of resource
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(InitKey)
#endif
@@ -515,6 +828,21 @@ IMG_VOID InitKey(HAND_KEY aKey, PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PV
aKey[HAND_KEY_PARENT] = (IMG_UINTPTR_T)hParent;
}
+/*!
+******************************************************************************
+
+ @Function ReallocHandleArray
+
+ @Description Reallocate the handle array
+
+ @Input psBase - handle base.
+ phBlockAlloc - pointer to block allocation handle.
+ ui32NewCount - new handle count
+ ui32OldCount - old handle count
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static
PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCount)
{
@@ -541,15 +869,15 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
if (((ui32OldCount % HANDLE_BLOCK_SIZE) != 0) ||
((ui32NewCount % HANDLE_BLOCK_SIZE) != 0))
{
- PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0)
- PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT((ui32OldCount % HANDLE_BLOCK_SIZE) == 0);
+ PVR_ASSERT((ui32NewCount % HANDLE_BLOCK_SIZE) == 0);
return PVRSRV_ERROR_INVALID_PARAMS;
}
if (ui32NewCount != 0)
{
-
+ /* Allocate new handle array */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
(IMG_VOID **)&psNewArray,
@@ -568,7 +896,10 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
}
}
-
+ /*
+ * If the new handle array is smaller than the old one, free
+ * unused handle structures
+ */
for(ui32Index = ui32NewCount; ui32Index < ui32OldCount; ui32Index += HANDLE_BLOCK_SIZE)
{
struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psOldArray, ui32Index);
@@ -583,10 +914,13 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
}
}
-
+ /*
+ * If the new handle array is bigger than the old one, allocate
+ * new handle structures
+ */
for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
{
-
+ /* PRQA S 0505 1 */ /* psNewArray is never NULL, see assert earlier */
struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
@@ -624,7 +958,7 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
}
#ifdef DEBUG_MAX_HANDLE_COUNT
-
+ /* Force handle failure to test error exit code */
if (ui32NewCount > DEBUG_MAX_HANDLE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR, "ReallocHandleArray: Max handle count (%u) reached", DEBUG_MAX_HANDLE_COUNT));
@@ -635,7 +969,7 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
if (psOldArray != IMG_NULL)
{
-
+ /* Free old handle array */
eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
HANDLE_ARRAY_SIZE(ui32OldCount) * sizeof(struct sHandleIndex),
psOldArray,
@@ -652,16 +986,21 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
if (ui32NewCount > ui32OldCount)
{
-
- PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount)
+ /* Check for wraparound */
+ PVR_ASSERT(psBase->ui32FreeHandCount + (ui32NewCount - ui32OldCount) > psBase->ui32FreeHandCount);
-
+ /* PRQA S 3382 1 */ /* ui32NewCount always > ui32OldCount */
psBase->ui32FreeHandCount += (ui32NewCount - ui32OldCount);
-
+ /*
+ * If purging is enabled, there is no free handle list
+ * management, but as an optimization, when allocating
+ * new handles, we use ui32FirstFreeIndex to point to
+ * the first handle in a newly allocated block.
+ */
if (psBase->ui32FirstFreeIndex == 0)
{
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
psBase->ui32FirstFreeIndex = ui32OldCount;
}
@@ -669,8 +1008,8 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
{
if (!psBase->bPurgingEnabled)
{
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
- PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32OldCount + 1;
}
@@ -683,11 +1022,11 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
}
else
{
- PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled)
- PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount)
- PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount)
+ PVR_ASSERT(ui32NewCount == 0 || psBase->bPurgingEnabled);
+ PVR_ASSERT(ui32NewCount == 0 || psBase->ui32FirstFreeIndex <= ui32NewCount);
+ PVR_ASSERT(psBase->ui32FreeHandCount - (ui32OldCount - ui32NewCount) < psBase->ui32FreeHandCount);
-
+ /* PRQA S 3382 1 */ /* ui32OldCount always >= ui32NewCount */
psBase->ui32FreeHandCount -= (ui32OldCount - ui32NewCount);
if (ui32NewCount == 0)
@@ -697,16 +1036,16 @@ PVRSRV_ERROR ReallocHandleArray(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32NewCo
}
}
- PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount)
+ PVR_ASSERT(psBase->ui32FirstFreeIndex <= psBase->ui32TotalHandCount);
return PVRSRV_OK;
error:
- PVR_ASSERT(eReturn != PVRSRV_OK)
+ PVR_ASSERT(eReturn != PVRSRV_OK);
if (psNewArray != IMG_NULL)
{
-
+ /* Free any new handle structures that were allocated */
for(ui32Index = ui32OldCount; ui32Index < ui32NewCount; ui32Index += HANDLE_BLOCK_SIZE)
{
struct sHandleIndex *psIndex = INDEX_TO_INDEX_STRUCT_PTR(psNewArray, ui32Index);
@@ -723,7 +1062,7 @@ error:
}
}
-
+ /* Free new handle array */
eError = OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
HANDLE_ARRAY_SIZE(ui32NewCount) * sizeof(struct sHandleIndex),
psNewArray,
@@ -737,18 +1076,52 @@ error:
return eReturn;
}
+/*!
+******************************************************************************
+
+ @Function FreeHandleArray
+
+ @Description Frees the handle array.
+ The memory containing the array of handle structure
+ pointers is deallocated.
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR FreeHandleArray(PVRSRV_HANDLE_BASE *psBase)
{
return ReallocHandleArray(psBase, 0);
}
+/*!
+******************************************************************************
+
+ @Function FreeHandle
+
+ @Description Free a handle structure.
+
+ @Input psBase - pointer to handle base structure
+ psHandle - pointer to handle structure
+
+ @Return PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHandle)
{
HAND_KEY aKey;
IMG_UINT32 ui32Index = HANDLE_PTR_TO_INDEX(psHandle);
PVRSRV_ERROR eError;
-
+ /*
+ * If a handle allocated in batch mode is freed whilst still
+ * in batch mode, the type is set to PVRSRV_HANDLE_TYPE_NONE further
+ * down, to indicate the handle will not be used, but not actually
+ * freed. The Free is completed when this function is called a
+ * second time as part of the batch commit or release.
+ */
+
InitKey(aKey, psBase, psHandle->pvData, psHandle->eType, ParentIfPrivate(psHandle));
if (!TEST_ALLOC_FLAG(psHandle, PVRSRV_HANDLE_ALLOC_FLAG_MULTI) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
@@ -762,15 +1135,15 @@ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHan
#endif
- PVR_ASSERT(hHandle != IMG_NULL)
- PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index))
+ PVR_ASSERT(hHandle != IMG_NULL);
+ PVR_ASSERT(hHandle == INDEX_TO_HANDLE(ui32Index));
PVR_UNREFERENCED_PARAMETER(hHandle);
}
-
+ /* Unlink handle from parent */
UnlinkFromParent(psBase, psHandle);
-
+ /* Free children */
eError = IterateOverChildren(psBase, psHandle, FreeHandle);
if (eError != PVRSRV_OK)
{
@@ -778,45 +1151,54 @@ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHan
return eError;
}
-
+ /*
+ * Clear the type here, so that a handle can no longer be looked
+ * up if it is only partially freed.
+ */
psHandle->eType = PVRSRV_HANDLE_TYPE_NONE;
if (BATCHED_HANDLE(psHandle) && !BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
{
-
+ /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
SET_BATCHED_HANDLE_PARTIALLY_FREE(psHandle);
-
+ /*
+ * If the handle was allocated in batch mode, delay the free
+ * until the batch commit or release.
+ */
return PVRSRV_OK;
}
-
+ /* No free list management if purging is enabled */
if (!psBase->bPurgingEnabled)
{
if (psBase->ui32FreeHandCount == 0)
{
- PVR_ASSERT(psBase->ui32FirstFreeIndex == 0)
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == 0);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == 0);
psBase->ui32FirstFreeIndex = ui32Index;
}
else
{
-
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0)
- PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0)
+ /*
+ * Put the handle pointer on the end of the the free
+ * handle pointer linked list.
+ */
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne != 0);
+ PVR_ASSERT(INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne == 0);
INDEX_TO_HANDLE_STRUCT_PTR(psBase, psBase->ui32LastFreeIndexPlusOne - 1)->ui32NextIndexPlusOne = ui32Index + 1;
}
- PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0)
+ PVR_ASSERT(psHandle->ui32NextIndexPlusOne == 0);
-
+ /* Update the end of the free handle linked list */
psBase->ui32LastFreeIndexPlusOne = ui32Index + 1;
}
psBase->ui32FreeHandCount++;
INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)++;
- PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE)
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32Index)<= HANDLE_BLOCK_SIZE);
#ifdef DEBUG
{
@@ -828,13 +1210,25 @@ static PVRSRV_ERROR FreeHandle(PVRSRV_HANDLE_BASE *psBase, struct sHandle *psHan
ui32FreeHandCount += INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32BlockedIndex);
}
- PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount)
+ PVR_ASSERT(ui32FreeHandCount == psBase->ui32FreeHandCount);
}
#endif
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function FreeAllHandles
+
+ @Description Free all handles for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return PVRSRV_OK or PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
{
IMG_UINT32 i;
@@ -860,7 +1254,7 @@ static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
break;
}
-
+ /* Break out of loop if all the handles free */
if (psBase->ui32FreeHandCount == psBase->ui32TotalHandCount)
{
break;
@@ -871,6 +1265,18 @@ static PVRSRV_ERROR FreeAllHandles(PVRSRV_HANDLE_BASE *psBase)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function FreeHandleBase
+
+ @Description Free a handle base.
+
+ @Input psHandleBase - pointer to handle base
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
{
PVRSRV_ERROR eError;
@@ -881,7 +1287,7 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
PVRSRVReleaseHandleBatch(psBase);
}
-
+ /* Free the handle array */
eError = FreeAllHandles(psBase);
if (eError != PVRSRV_OK)
{
@@ -889,7 +1295,7 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
return eError;
}
-
+ /* Free the handle array */
eError = FreeHandleArray(psBase);
if (eError != PVRSRV_OK)
{
@@ -899,7 +1305,7 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
if (psBase->psHashTab != IMG_NULL)
{
-
+ /* Free the hash table */
HASH_Delete(psBase->psHashTab);
}
@@ -916,6 +1322,20 @@ static PVRSRV_ERROR FreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function FindHandle
+
+ @Description Find handle corresponding to a resource pointer
+
+ @Input psBase - pointer to handle base structure
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Return the handle, or IMG_NULL if not found
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(FindHandle)
#endif
@@ -928,7 +1348,7 @@ IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDL
{
HAND_KEY aKey;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
InitKey(aKey, psBase, pvData, eType, hParent);
@@ -939,16 +1359,30 @@ IMG_HANDLE FindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_VOID *pvData, PVRSRV_HANDL
#endif
}
+/*!
+******************************************************************************
+
+ @Function IncreaseHandleArraySize
+
+ @Description Allocate some more free handles
+
+ @Input psBase - pointer to handle base structure
+ ui32Delta - number of new handles required
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Delta)
{
PVRSRV_ERROR eError;
IMG_UINT32 ui32DeltaAdjusted = ROUND_UP_TO_MULTIPLE_OF_BLOCK_SIZE(ui32Delta);
IMG_UINT32 ui32NewTotalHandCount = psBase->ui32TotalHandCount + ui32DeltaAdjusted;
-;
- PVR_ASSERT(ui32Delta != 0)
+ PVR_ASSERT(ui32Delta != 0);
-
+ /*
+ * Check new count against max handle index, and check for wrap around.
+ */
if (ui32NewTotalHandCount > psBase->ui32MaxIndexPlusOne || ui32NewTotalHandCount <= psBase->ui32TotalHandCount)
{
ui32NewTotalHandCount = psBase->ui32MaxIndexPlusOne;
@@ -962,9 +1396,9 @@ static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT
}
}
- PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta)
+ PVR_ASSERT(ui32DeltaAdjusted >= ui32Delta);
-
+ /* Realloc handle pointer array */
eError = ReallocHandleArray(psBase, ui32NewTotalHandCount);
if (eError != PVRSRV_OK)
{
@@ -975,6 +1409,19 @@ static PVRSRV_ERROR IncreaseHandleArraySize(PVRSRV_HANDLE_BASE *psBase, IMG_UINT
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function EnsureFreeHandles
+
+ @Description Ensure there are enough free handles
+
+ @Input psBase - pointer to handle base structure
+ ui32Free - number of free handles required
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Free)
{
PVRSRV_ERROR eError;
@@ -994,6 +1441,23 @@ static PVRSRV_ERROR EnsureFreeHandles(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui3
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function AllocHandle
+
+ @Description Allocate a new handle
+
+ @Input phHandle - location for new handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+ hParent - parent handle or IMG_NULL
+
+ @Output phHandle - points to new handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
#else
@@ -1010,15 +1474,15 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle
HAND_KEY aKey;
PVRSRV_ERROR eError;
-
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
- PVR_ASSERT(psBase != IMG_NULL)
- PVR_ASSERT(psBase->psHashTab != IMG_NULL)
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
+ PVR_ASSERT(psBase != IMG_NULL);
+ PVR_ASSERT(psBase->psHashTab != IMG_NULL);
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
- PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL)
+ /* Handle must not already exist */
+ PVR_ASSERT(FindHandle(psBase, pvData, eType, hParent) == IMG_NULL);
}
if (psBase->ui32FreeHandCount == 0 && HANDLES_BATCHED(psBase))
@@ -1026,30 +1490,41 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle
PVR_DPF((PVR_DBG_WARNING, "AllocHandle: Handle batch size (%u) was too small, allocating additional space", psBase->ui32HandBatchSize));
}
-
+ /* Ensure there is a free handle */
eError = EnsureFreeHandles(psBase, 1);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "AllocHandle: EnsureFreeHandles failed (%d)", eError));
return eError;
}
- PVR_ASSERT(psBase->ui32FreeHandCount != 0)
+ PVR_ASSERT(psBase->ui32FreeHandCount != 0);
if (!psBase->bPurgingEnabled)
{
-
+ /* Array index of first free handle */
ui32NewIndex = psBase->ui32FirstFreeIndex;
-
+ /* Get handle array entry */
psNewHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32NewIndex);
}
else
{
IMG_UINT32 ui32BlockedIndex;
-
-
- PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0)
+ /*
+ * If purging is enabled, we always try to allocate handles
+ * at the front of the array, to increase the chances that
+ * the size of the handle array can be reduced by a purge.
+ * No linked list of free handles is kept; we search for
+ * free handles as required.
+ */
+
+ /*
+ * ui32FirstFreeIndex should only be set when a new batch of
+ * handle structures is allocated, and should always be a
+ * multiple of the block size.
+ */
+ PVR_ASSERT((psBase->ui32FirstFreeIndex % HANDLE_BLOCK_SIZE) == 0);
for (ui32BlockedIndex = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(psBase->ui32FirstFreeIndex); ui32BlockedIndex < psBase->ui32TotalHandCount; ui32BlockedIndex += HANDLE_BLOCK_SIZE)
{
@@ -1070,20 +1545,24 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle
}
}
psBase->ui32FirstFreeIndex = 0;
- PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount)
+ PVR_ASSERT(ui32NewIndex < psBase->ui32TotalHandCount);
}
- PVR_ASSERT(psNewHandle != IMG_NULL)
+ PVR_ASSERT(psNewHandle != IMG_NULL);
-
+ /* Handle to be returned to client */
hHandle = INDEX_TO_HANDLE(ui32NewIndex);
-
+ /*
+ * If a data pointer can be associated with multiple handles, we
+ * don't put the handle in the hash table, as the data pointer
+ * may not map to a unique handle
+ */
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
+ /* Initialise hash key */
InitKey(aKey, psBase, pvData, eType, hParent);
-
+ /* Put the new handle in the hash table */
if (!HASH_Insert_Extended(psBase->psHashTab, aKey, (IMG_UINTPTR_T)hHandle))
{
PVR_DPF((PVR_DBG_ERROR, "AllocHandle: Couldn't add handle to hash table"));
@@ -1094,36 +1573,44 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle
psBase->ui32FreeHandCount--;
- PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE)
- PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0)
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) <= HANDLE_BLOCK_SIZE);
+ PVR_ASSERT(INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex) > 0);
INDEX_TO_FREE_HAND_BLOCK_COUNT(psBase, ui32NewIndex)--;
-
+ /* No free list management if purging is enabled */
if (!psBase->bPurgingEnabled)
{
-
+ /* Check whether the last free handle has been allocated */
if (psBase->ui32FreeHandCount == 0)
{
- PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex)
- PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1))
+ PVR_ASSERT(psBase->ui32FirstFreeIndex == ui32NewIndex);
+ PVR_ASSERT(psBase->ui32LastFreeIndexPlusOne == (ui32NewIndex + 1));
psBase->ui32LastFreeIndexPlusOne = 0;
psBase->ui32FirstFreeIndex = 0;
}
else
{
-
+ /*
+ * Update the first free handle index.
+ * If the "next free index plus one" field in the new
+ * handle structure is zero, the next free index is
+ * the index of the new handle plus one. This
+ * convention has been adopted to simplify the
+ * initialisation of freshly allocated handle
+ * space.
+ */
psBase->ui32FirstFreeIndex = (psNewHandle->ui32NextIndexPlusOne == 0) ?
ui32NewIndex + 1 :
psNewHandle->ui32NextIndexPlusOne - 1;
}
}
-
- PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex)
+ /* Initialise the newly allocated handle */
+ PVR_ASSERT(psNewHandle->ui32Index == ui32NewIndex);
-
+ /* PRQA S 0505 1 */ /* psNewHandle is never NULL, see assert earlier */
psNewHandle->eType = eType;
psNewHandle->pvData = pvData;
psNewHandle->eInternalFlag = INTERNAL_HANDLE_FLAG_NONE;
@@ -1131,22 +1618,22 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle
InitParentList(psNewHandle);
#if defined(DEBUG)
- PVR_ASSERT(NoChildren(psNewHandle))
+ PVR_ASSERT(NoChildren(psNewHandle));
#endif
InitChildEntry(psNewHandle);
#if defined(DEBUG)
- PVR_ASSERT(NoParent(psNewHandle))
+ PVR_ASSERT(NoParent(psNewHandle));
#endif
if (HANDLES_BATCHED(psBase))
{
-
+ /* Add handle to batch list */
psNewHandle->ui32NextIndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
psBase->ui32FirstBatchIndexPlusOne = ui32NewIndex + 1;
-
+ /* PRQA S 1474 1 */ /* ignore warnings about enum types being modified */
SET_BATCHED_HANDLE(psNewHandle);
}
else
@@ -1154,12 +1641,28 @@ static PVRSRV_ERROR AllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle
psNewHandle->ui32NextIndexPlusOne = 0;
}
-
+ /* Return the new handle to the client */
*phHandle = hHandle;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocHandle
+
+ @Description Allocate a handle
+
+ @Input phHandle - location for new handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Output phHandle - points to new handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag)
#else
@@ -1181,16 +1684,19 @@ PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle,
if (HANDLES_BATCHED(psBase))
{
-
+ /*
+ * Increment the counter in case of failure. It will be
+ * decremented on success.
+ */
psBase->ui32BatchHandAllocFailures++;
}
-
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
+ /* See if there is already a handle for this data pointer */
hHandle = FindHandle(psBase, pvData, eType, IMG_NULL);
#if defined (SUPPORT_SID_INTERFACE)
if (hHandle != 0)
@@ -1207,7 +1713,11 @@ PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle,
return eError;
}
-
+ /*
+ * If the client is willing to share a handle, and the
+ * existing handle is marked as shareable, return the
+ * existing handle.
+ */
if (TEST_FLAG(psHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED))
{
*phHandle = hHandle;
@@ -1233,6 +1743,23 @@ exit_ok:
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocSubHandle
+
+ @Description Allocate a subhandle
+
+ @Input phHandle - location for new subhandle
+ pvData - pointer to resource to be associated with the subhandle
+ eType - the type of resource
+ hParent - parent handle
+
+ @Output phHandle - points to new subhandle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType, PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_SID hParent)
#else
@@ -1256,17 +1783,20 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand
if (HANDLES_BATCHED(psBase))
{
-
+ /*
+ * Increment the counter in case of failure. It will be
+ * decremented on success.
+ */
psBase->ui32BatchHandAllocFailures++;
}
-
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ /* PVRSRV_HANDLE_TYPE_NONE is reserved for internal use */
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
hParentKey = TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE) ?
hParent : IMG_NULL;
-
+ /* Lookup the parent handle */
eError = GetHandleStructure(psBase, &psPHand, hParent, PVRSRV_HANDLE_TYPE_NONE);
if (eError != PVRSRV_OK)
{
@@ -1275,7 +1805,7 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand
if (!TEST_FLAG(eFlag, PVRSRV_HANDLE_ALLOC_FLAG_MULTI))
{
-
+ /* See if there is already a handle for this data pointer */
hHandle = FindHandle(psBase, pvData, eType, hParentKey);
#if defined (SUPPORT_SID_INTERFACE)
if (hHandle != 0)
@@ -1293,9 +1823,14 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand
return eErr;
}
- PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
+ PVR_ASSERT(hParentKey != IMG_NULL && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent);
-
+ /*
+ * If the client is willing to share a handle, the
+ * existing handle is marked as shareable, and the
+ * existing handle has the same parent, return the
+ * existing handle.
+ */
if (TEST_FLAG(psCHandle->eFlag & eFlag, PVRSRV_HANDLE_ALLOC_FLAG_SHARED) && ParentHandle(HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle)) == hParent)
{
*phHandle = hHandle;
@@ -1314,7 +1849,11 @@ PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHand
return eError;
}
-
+ /*
+ * Get the parent handle structure again, in case the handle
+ * structure has moved (depending on the implementation
+ * of AllocHandle).
+ */
psPHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hParent);
psCHand = HANDLE_TO_HANDLE_STRUCT_PTR(psBase, hHandle);
@@ -1332,6 +1871,22 @@ exit_ok:
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFindHandle
+
+ @Description Find handle corresponding to a resource pointer
+
+ @Input phHandle - location for returned handle
+ pvData - pointer to resource to be associated with the handle
+ eType - the type of resource
+
+ @Output phHandle - points to handle
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType)
#else
@@ -1344,9 +1899,9 @@ PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle,
IMG_HANDLE hHandle;
#endif
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
-
+ /* See if there is a handle for this data pointer */
#if defined (SUPPORT_SID_INTERFACE)
hHandle = (IMG_SID) FindHandle(psBase, pvData, eType, IMG_NULL);
#else
@@ -1362,6 +1917,23 @@ PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE *phHandle,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupHandleAnyType
+
+ @Description Lookup the data pointer and type corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ peType - location to return handle type
+ hHandle - handle from client
+
+ @Output ppvData - points to the data pointer
+ peType - points to handle type
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_SID hHandle)
#else
@@ -1387,6 +1959,22 @@ PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *pp
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupHandle
+
+ @Description Lookup the data pointer corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
@@ -1396,9 +1984,9 @@ PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData,
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
#if defined (SUPPORT_SID_INTERFACE)
- PVR_ASSERT(hHandle != 0)
+ PVR_ASSERT(hHandle != 0);
#endif
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
@@ -1416,6 +2004,23 @@ PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupSubHandle
+
+ @Description Lookup the data pointer corresponding to a subhandle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+ hAncestor - ancestor handle
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType, IMG_SID hAncestor)
#else
@@ -1426,9 +2031,9 @@ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvDat
struct sHandle *psCHand;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
#if defined (SUPPORT_SID_INTERFACE)
- PVR_ASSERT(hHandle != 0)
+ PVR_ASSERT(hHandle != 0);
#endif
eError = GetHandleStructure(psBase, &psCHand, hHandle, eType);
@@ -1438,7 +2043,7 @@ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvDat
return eError;
}
-
+ /* Look for hAncestor among the handle's ancestors */
for (psPHand = psCHand; ParentHandle(psPHand) != hAncestor; )
{
eError = GetHandleStructure(psBase, &psPHand, ParentHandle(psPHand), PVRSRV_HANDLE_TYPE_NONE);
@@ -1454,6 +2059,24 @@ PVRSRV_ERROR PVRSRVLookupSubHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvDat
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetParentHandle
+
+ @Description Lookup the parent of a handle
+
+ @Input phParent - location for returning parent handle
+ hHandle - handle for which the parent handle is required
+ eType - handle type
+ hParent - parent handle
+
+ @Output *phParent - parent handle, or IMG_NULL if there is no parent
+
+ @Return Error code or PVRSRV_OK. Note that not having a parent is
+ not regarded as an error.
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID *phParent, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
@@ -1463,7 +2086,7 @@ PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phPare
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
if (eError != PVRSRV_OK)
@@ -1477,6 +2100,23 @@ PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phPare
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVLookupAndReleaseHandle
+
+ @Description Lookup the data pointer corresponding to a handle
+
+ @Input ppvData - location to return data pointer
+ hHandle - handle from client
+ eType - handle type
+ eFlag - lookup flags
+
+ @Output ppvData - points to the data pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
@@ -1486,7 +2126,7 @@ PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
if (eError != PVRSRV_OK)
@@ -1505,6 +2145,19 @@ PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVReleaseHandle
+
+ @Description Release a handle that is no longer needed
+
+ @Input hHandle - handle from client
+ eType - handle type
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_SID hHandle, PVRSRV_HANDLE_TYPE eType)
#else
@@ -1514,7 +2167,7 @@ PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle,
struct sHandle *psHandle;
PVRSRV_ERROR eError;
- PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE)
+ PVR_ASSERT(eType != PVRSRV_HANDLE_TYPE_NONE);
eError = GetHandleStructure(psBase, &psHandle, hHandle, eType);
if (eError != PVRSRV_OK)
@@ -1528,6 +2181,19 @@ PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle,
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVNewHandleBatch
+
+ @Description Start a new handle batch
+
+ @Input psBase - handle base
+ @Input ui32BatchSize - handle batch size
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize)
{
PVRSRV_ERROR eError;
@@ -1553,18 +2219,31 @@ PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32Bat
psBase->ui32HandBatchSize = ui32BatchSize;
-
+ /* Record current number of handles */
psBase->ui32TotalHandCountPreBatch = psBase->ui32TotalHandCount;
- PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0)
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0);
- PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0)
+ PVR_ASSERT(psBase->ui32FirstBatchIndexPlusOne == 0);
- PVR_ASSERT(HANDLES_BATCHED(psBase))
+ PVR_ASSERT(HANDLES_BATCHED(psBase));
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleBatchCommitOrRelease
+
+ @Description Release a handle batch
+
+ @Input psBase - handle base
+ bCommit - commit handles
+
+ @Return none
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase, IMG_BOOL bCommit)
{
@@ -1587,24 +2266,32 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase,
}
bCommitBatch = IMG_FALSE;
}
-
- PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit)
+ /*
+ * The whole point of batched handles is to avoid handle allocation
+ * failures.
+ */
+ PVR_ASSERT(psBase->ui32BatchHandAllocFailures == 0 || !bCommit);
ui32IndexPlusOne = psBase->ui32FirstBatchIndexPlusOne;
while(ui32IndexPlusOne != 0)
{
struct sHandle *psHandle = INDEX_TO_HANDLE_STRUCT_PTR(psBase, ui32IndexPlusOne - 1);
IMG_UINT32 ui32NextIndexPlusOne = psHandle->ui32NextIndexPlusOne;
- PVR_ASSERT(BATCHED_HANDLE(psHandle))
+ PVR_ASSERT(BATCHED_HANDLE(psHandle));
psHandle->ui32NextIndexPlusOne = 0;
if (!bCommitBatch || BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
{
+ /*
+ * We need a complete free here. If the handle
+ * is not partially free, set the handle as
+ * unbatched to avoid a partial free.
+ */
if (!BATCHED_HANDLE_PARTIALLY_FREE(psHandle))
{
-
- SET_UNBATCHED_HANDLE(psHandle);
+ /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
+ SET_UNBATCHED_HANDLE(psHandle); /* PRQA S 4130 */ /* mis-use of enums FIXME*/
}
eError = FreeHandle(psBase, psHandle);
@@ -1612,11 +2299,11 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase,
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVHandleBatchCommitOrRelease: Error freeing handle (%d)", eError));
}
- PVR_ASSERT(eError == PVRSRV_OK)
+ PVR_ASSERT(eError == PVRSRV_OK);
}
else
{
-
+ /* PRQA S 1474,4130 1 */ /* ignore warnings about enum types being modified */
SET_UNBATCHED_HANDLE(psHandle);
}
@@ -1628,7 +2315,7 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase,
{
IMG_UINT32 ui32Delta = psBase->ui32TotalHandCount - psBase->ui32TotalHandCountPreBatch;
- PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch)
+ PVR_ASSERT(psBase->ui32TotalHandCount > psBase->ui32TotalHandCountPreBatch);
PVR_DPF((PVR_DBG_WARNING, "PVRSRVHandleBatchCommitOrRelease: The batch size was too small. Batch size was %u, but needs to be %u", psBase->ui32HandBatchSize, psBase->ui32HandBatchSize + ui32Delta));
@@ -1639,7 +2326,7 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase,
if (psBase->ui32BatchHandAllocFailures != 0 && bCommit)
{
- PVR_ASSERT(!bCommitBatch)
+ PVR_ASSERT(!bCommitBatch);
eError = PVRSRV_ERROR_HANDLE_BATCH_COMMIT_FAILURE;
}
@@ -1652,16 +2339,53 @@ static PVRSRV_ERROR PVRSRVHandleBatchCommitOrRelease(PVRSRV_HANDLE_BASE *psBase,
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVCommitHandleBatch
+
+ @Description Commit a handle batch
+
+ @Input psBase - handle base
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
{
return PVRSRVHandleBatchCommitOrRelease(psBase, IMG_TRUE);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRReleaseHandleBatch
+
+ @Description Release a handle batch
+
+ @Input psBase - handle base
+
+ @Return none
+
+******************************************************************************/
IMG_VOID PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
{
(IMG_VOID) PVRSRVHandleBatchCommitOrRelease(psBase, IMG_FALSE);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetMaxHandle
+
+ @Description Set maximum handle number for given handle base
+
+ @Input psBase - pointer to handle base structure
+ ui32MaxHandle - Maximum handle number
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHandle)
{
IMG_UINT32 ui32MaxHandleRounded;
@@ -1672,7 +2396,7 @@ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHa
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* Validate the limit */
if (ui32MaxHandle == 0 || ui32MaxHandle > DEFAULT_MAX_HANDLE)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit must be between %u and %u, inclusive", 0, DEFAULT_MAX_HANDLE));
@@ -1680,7 +2404,7 @@ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHa
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* The limit can only be set if no handles have been allocated */
if (psBase->ui32TotalHandCount != 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVSetMaxHandle: Limit cannot be set because handles have already been allocated"));
@@ -1690,24 +2414,54 @@ PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32MaxHa
ui32MaxHandleRounded = ROUND_DOWN_TO_MULTIPLE_OF_BLOCK_SIZE(ui32MaxHandle);
-
+ /*
+ * Allow the maximum number of handles to be reduced, but never to
+ * zero.
+ */
if (ui32MaxHandleRounded != 0 && ui32MaxHandleRounded < psBase->ui32MaxIndexPlusOne)
{
psBase->ui32MaxIndexPlusOne = ui32MaxHandleRounded;
}
- PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0)
- PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE)
- PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne != 0);
+ PVR_ASSERT(psBase->ui32MaxIndexPlusOne <= DEFAULT_MAX_INDEX_PLUS_ONE);
+ PVR_ASSERT((psBase->ui32MaxIndexPlusOne % HANDLE_BLOCK_SIZE) == 0);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetMaxHandle
+
+ @Description Get maximum handle number for given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Output Maximum handle number, or 0 if handle limits not
+ supported.
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
{
return psBase->ui32MaxIndexPlusOne;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnableHandlePurging
+
+ @Description Enable purging for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
{
if (psBase->bPurgingEnabled)
@@ -1716,7 +2470,7 @@ PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
return PVRSRV_OK;
}
-
+ /* Purging can only be enabled if no handles have been allocated */
if (psBase->ui32TotalHandCount != 0)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVEnableHandlePurging: Handles have already been allocated"));
@@ -1728,6 +2482,18 @@ PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPurgeHandles
+
+ @Description Purge handles for a given handle base
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
{
IMG_UINT32 ui32BlockIndex;
@@ -1745,7 +2511,7 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
return PVRSRV_ERROR_INVALID_PARAMS;
}
- PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0)
+ PVR_ASSERT((psBase->ui32TotalHandCount % HANDLE_BLOCK_SIZE) == 0);
for (ui32BlockIndex = INDEX_TO_BLOCK_INDEX(psBase->ui32TotalHandCount); ui32BlockIndex != 0; ui32BlockIndex--)
{
@@ -1756,12 +2522,14 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
}
ui32NewHandCount = BLOCK_INDEX_TO_INDEX(ui32BlockIndex);
-
+ /*
+ * Check for a suitable decrease in the handle count.
+ */
if (ui32NewHandCount <= (psBase->ui32TotalHandCount/2))
{
PVRSRV_ERROR eError;
-
+ // PVR_TRACE((" PVRSRVPurgeHandles: reducing number of handles from %u to %u", psBase->ui32TotalHandCount, ui32NewHandCount));
eError = ReallocHandleArray(psBase, ui32NewHandCount);
if (eError != PVRSRV_OK)
@@ -1773,6 +2541,20 @@ PVRSRV_ERROR PVRSRVPurgeHandles(PVRSRV_HANDLE_BASE *psBase)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAllocHandleBase
+
+ @Description Allocate a handle base structure for a process
+
+ @Input ppsBase - pointer to handle base structure pointer
+
+ @Output ppsBase - points to handle base structure pointer
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
{
PVRSRV_HANDLE_BASE *psBase;
@@ -1791,7 +2573,7 @@ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
}
OSMemSet(psBase, 0, sizeof(*psBase));
-
+ /* Create hash table */
psBase->psHashTab = HASH_Create_Extended(HANDLE_HASH_TAB_INIT_SIZE, sizeof(HAND_KEY), HASH_Func_Default, HASH_Key_Comp_Default);
if (psBase->psHashTab == IMG_NULL)
{
@@ -1809,11 +2591,23 @@ PVRSRV_ERROR PVRSRVAllocHandleBase(PVRSRV_HANDLE_BASE **ppsBase)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFreeHandleBase
+
+ @Description Free a handle base structure
+
+ @Input psBase - pointer to handle base structure
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
{
PVRSRV_ERROR eError;
- PVR_ASSERT(psBase != gpsKernelHandleBase)
+ PVR_ASSERT(psBase != gpsKernelHandleBase);
eError = FreeHandleBase(psBase);
if (eError != PVRSRV_OK)
@@ -1824,11 +2618,21 @@ PVRSRV_ERROR PVRSRVFreeHandleBase(PVRSRV_HANDLE_BASE *psBase)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleInit
+
+ @Description Initialise handle management
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID)
{
PVRSRV_ERROR eError;
- PVR_ASSERT(gpsKernelHandleBase == IMG_NULL)
+ PVR_ASSERT(gpsKernelHandleBase == IMG_NULL);
eError = PVRSRVAllocHandleBase(&gpsKernelHandleBase);
if (eError != PVRSRV_OK)
@@ -1850,6 +2654,16 @@ error:
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVHandleDeInit
+
+ @Description De-initialise handle management
+
+ @Return Error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
{
PVRSRV_ERROR eError = PVRSRV_OK;
@@ -1870,4 +2684,8 @@ PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
return eError;
}
#else
-#endif
+/* disable warning about empty module */
+#endif /* #if defined(PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE) */
+/******************************************************************************
+ End of file (handle.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/hash.c b/sgx/services4/srvkm/common/hash.c
index 78eab44..a3791fa 100644
--- a/sgx/services4/srvkm/common/hash.c
+++ b/sgx/services4/srvkm/common/hash.c
@@ -1,28 +1,50 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Self scaling hash tables.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+@Description
+ Implements simple self scaling hash tables. Hash collisions are
+ handled by chaining entries together. Hash tables are increased in
+ size when they become more than (50%?) full and decreased in size
+ when less than (25%?) full. Hash tables are never decreased below
+ their initial size.
+*/ /**************************************************************************/
#include "pvr_debug.h"
#include "img_defs.h"
@@ -39,43 +61,57 @@
#define KEY_COMPARE(pHash, pKey1, pKey2) \
((pHash)->pfnKeyComp((pHash)->uKeySize, (pKey1), (pKey2)))
+/* Each entry in a hash table is placed into a bucket */
struct _BUCKET_
{
-
+ /* the next bucket on the same chain */
struct _BUCKET_ *pNext;
-
+ /* entry value */
IMG_UINTPTR_T v;
-
- IMG_UINTPTR_T k[];
+ /* entry key */
+ IMG_UINTPTR_T k[]; /* PRQA S 0642 */ /* override dynamic array declaration warning */
};
typedef struct _BUCKET_ BUCKET;
struct _HASH_TABLE_
{
-
+ /* the hash table array */
BUCKET **ppBucketTable;
-
+ /* current size of the hash table */
IMG_UINT32 uSize;
-
+ /* number of entries currently in the hash table */
IMG_UINT32 uCount;
-
+ /* the minimum size that the hash table should be re-sized to */
IMG_UINT32 uMinimumSize;
-
+ /* size of key in bytes */
IMG_UINT32 uKeySize;
-
+ /* hash function */
HASH_FUNC *pfnHashFunc;
-
+ /* key comparison function */
HASH_KEY_COMP *pfnKeyComp;
};
+/*!
+******************************************************************************
+ @Function HASH_Func_Default
+
+ @Description Hash function intended for hashing keys composed of
+ IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey - a pointer to the key to hash.
+ @Input uHashTabLen - the length of the hash table.
+
+ @Return the hash value.
+******************************************************************************/
IMG_UINT32
HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
{
@@ -107,6 +143,18 @@ HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen)
return uHashKey;
}
+/*!
+******************************************************************************
+ @Function HASH_Key_Comp_Default
+
+ @Description Compares keys composed of IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey1 - pointer to first hash key to compare.
+ @Input pKey2 - pointer to second hash key to compare.
+ @Return IMG_TRUE - the keys match.
+ IMG_FALSE - the keys don't match.
+******************************************************************************/
IMG_BOOL
HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
{
@@ -126,6 +174,18 @@ HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2)
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ @Function _ChainInsert
+
+ @Description Insert a bucket into the appropriate hash table chain.
+
+ @Input pBucket - the bucket
+ @Input ppBucketTable - the hash table
+ @Input uSize - the size of the hash table
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR
_ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UINT32 uSize)
{
@@ -141,13 +201,27 @@ _ChainInsert (HASH_TABLE *pHash, BUCKET *pBucket, BUCKET **ppBucketTable, IMG_UI
return PVRSRV_ERROR_INVALID_PARAMS;
}
- uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize);
+ uIndex = KEY_TO_INDEX(pHash, pBucket->k, uSize); /* PRQA S 0432,0541 */ /* ignore dynamic array warning */
pBucket->pNext = ppBucketTable[uIndex];
ppBucketTable[uIndex] = pBucket;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function _Rehash
+
+ @Description Iterate over every entry in an old hash table and
+ rehash into the new table.
+
+ @Input ppOldTable - the old hash table
+ @Input uOldSize - the size of the old hash table
+ @Input ppNewTable - the new hash table
+ @Input uNewSize - the size of the new hash table
+
+ @Return None
+******************************************************************************/
static PVRSRV_ERROR
_Rehash (HASH_TABLE *pHash,
BUCKET **ppOldTable, IMG_UINT32 uOldSize,
@@ -174,6 +248,20 @@ _Rehash (HASH_TABLE *pHash,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function _Resize
+
+ @Description Attempt to resize a hash table, failure to allocate a
+ new larger hash table is not considered a hard failure.
+ We simply continue and allow the table to fill up, the
+ effect is to allow hash chains to become longer.
+
+ @Input pHash - Hash table to resize.
+ @Input uNewSize - Required table size.
+ @Return IMG_TRUE Success
+ IMG_FALSE Failed
+******************************************************************************/
static IMG_BOOL
_Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
{
@@ -202,7 +290,7 @@ _Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
}
OSFreeMem (PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
-
+ /*not nulling pointer, being reassigned just below*/
pHash->ppBucketTable = ppNewTable;
pHash->uSize = uNewSize;
}
@@ -210,6 +298,23 @@ _Resize (HASH_TABLE *pHash, IMG_UINT32 uNewSize)
}
+/*!
+******************************************************************************
+ @Function HASH_Create_Extended
+
+ @Description Create a self scaling hash table, using the supplied
+ key size, and the supplied hash and key comparsion
+ functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the number
+ of entries in the hash table, not its size in
+ bytes.
+ @Input uKeySize - the size of the key, in bytes.
+ @Input pfnHashFunc - pointer to hash function.
+ @Input pfnKeyComp - pointer to key comparsion function.
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp)
{
HASH_TABLE *pHash;
@@ -240,7 +345,7 @@ HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize,
if (pHash->ppBucketTable == IMG_NULL)
{
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_NULL;
}
@@ -249,12 +354,38 @@ HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize,
return pHash;
}
+/*!
+******************************************************************************
+ @Function HASH_Create
+
+ @Description Create a self scaling hash table with a key
+ consisting of a single IMG_UINTPTR_T, and using
+ the default hash and key comparison functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the
+ number of entries in the hash table, not its size
+ in bytes.
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen)
{
return HASH_Create_Extended(uInitialLen, sizeof(IMG_UINTPTR_T),
&HASH_Func_Default, &HASH_Key_Comp_Default);
}
+/*!
+******************************************************************************
+ @Function HASH_Delete
+
+ @Description Delete a hash table created by HASH_Create_Extended or
+ HASH_Create. All entries in the table must have been
+ removed before calling this function.
+
+ @Input pHash - hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID
HASH_Delete (HASH_TABLE *pHash)
{
@@ -271,10 +402,24 @@ HASH_Delete (HASH_TABLE *pHash)
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET *)*pHash->uSize, pHash->ppBucketTable, IMG_NULL);
pHash->ppBucketTable = IMG_NULL;
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(HASH_TABLE), pHash, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
+ @Function HASH_Insert_Extended
+
+ @Description Insert a key value pair into a hash table created
+ with HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success
+ IMG_FALSE - failure
+******************************************************************************/
IMG_BOOL
HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
{
@@ -301,7 +446,7 @@ HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
}
pBucket->v = v;
-
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k (linux)*/
OSMemCopy(pBucket->k, pKey, pHash->uKeySize);
if (_ChainInsert (pHash, pBucket, pHash->ppBucketTable, pHash->uSize) != PVRSRV_OK)
{
@@ -313,11 +458,12 @@ HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
pHash->uCount++;
-
+ /* check if we need to think about re-balencing */
if (pHash->uCount << 1 > pHash->uSize)
{
-
-
+ /* Ignore the return code from _Resize because the hash table is
+ still in a valid state and although not ideally sized, it is still
+ functional */
_Resize (pHash, pHash->uSize << 1);
}
@@ -325,6 +471,20 @@ HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v)
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ @Function HASH_Insert
+
+ @Description Insert a key value pair into a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table.
+ @Input k - the key value.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+******************************************************************************/
IMG_BOOL
HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
{
@@ -335,6 +495,19 @@ HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v)
return HASH_Insert_Extended(pHash, &k, v);
}
+/*!
+******************************************************************************
+ @Function HASH_Remove_Extended
+
+ @Description Remove a key from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to key.
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
{
@@ -356,7 +529,7 @@ HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
{
-
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
{
BUCKET *pBucket = *ppBucket;
@@ -364,16 +537,17 @@ HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
(*ppBucket) = pBucket->pNext;
OSFreeMem(PVRSRV_PAGEABLE_SELECT, sizeof(BUCKET) + pHash->uKeySize, pBucket, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
pHash->uCount--;
-
+ /* check if we need to think about re-balencing */
if (pHash->uSize > (pHash->uCount << 2) &&
pHash->uSize > pHash->uMinimumSize)
{
-
-
+ /* Ignore the return code from _Resize because the
+ hash table is still in a valid state and although
+ not ideally sized, it is still functional */
_Resize (pHash,
PRIVATE_MAX (pHash->uSize >> 1,
pHash->uMinimumSize));
@@ -391,6 +565,19 @@ HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey)
return 0;
}
+/*!
+******************************************************************************
+ @Function HASH_Remove
+
+ @Description Remove a key value pair from a hash table created
+ with HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
{
@@ -400,6 +587,19 @@ HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k)
return HASH_Remove_Extended(pHash, &k);
}
+/*!
+******************************************************************************
+ @Function HASH_Retrieve_Extended
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
{
@@ -421,7 +621,7 @@ HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
for (ppBucket = &(pHash->ppBucketTable[uIndex]); *ppBucket != IMG_NULL; ppBucket = &((*ppBucket)->pNext))
{
-
+ /* PRQA S 0432,0541 1 */ /* ignore warning about dynamic array k */
if (KEY_COMPARE(pHash, (*ppBucket)->k, pKey))
{
BUCKET *pBucket = *ppBucket;
@@ -439,6 +639,18 @@ HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey)
return 0;
}
+/*!
+******************************************************************************
+ @Function HASH_Retrieve
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T
HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
{
@@ -447,6 +659,17 @@ HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k)
return HASH_Retrieve_Extended(pHash, &k);
}
+/*!
+******************************************************************************
+ @Function HASH_Iterate
+
+ @Description Iterate over every entry in the hash table
+
+ @Input pHash - the old hash table
+ @Input pfnCallback - the size of the old hash table
+
+ @Return Callback error if any, otherwise PVRSRV_OK
+******************************************************************************/
PVRSRV_ERROR
HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
{
@@ -462,7 +685,7 @@ HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
eError = pfnCallback((IMG_UINTPTR_T) ((IMG_VOID *) *(pBucket->k)), (IMG_UINTPTR_T) pBucket->v);
-
+ /* The callback might want us to break out early */
if (eError != PVRSRV_OK)
return eError;
@@ -473,6 +696,17 @@ HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback)
}
#ifdef HASH_TRACE
+/*!
+******************************************************************************
+ @Function HASH_Dump
+
+ @Description To dump the contents of a hash table in human readable
+ form.
+
+ @Input pHash - the hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID
HASH_Dump (HASH_TABLE *pHash)
{
diff --git a/sgx/services4/srvkm/common/lists.c b/sgx/services4/srvkm/common/lists.c
index 1081781..038cab1 100644
--- a/sgx/services4/srvkm/common/lists.c
+++ b/sgx/services4/srvkm/common/lists.c
@@ -1,32 +1,54 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linked list shared functions implementation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implementation of the list iterators for types shared among
+ more than one file in the services code.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "lists.h"
#include "services_headers.h"
+/*===================================================================
+ LIST ITERATOR FUNCTIONS USED IN MORE THAN ONE FILE (those used just
+ once are implemented locally).
+ ===================================================================*/
+
IMPLEMENT_LIST_ANY_VA(BM_HEAP)
IMPLEMENT_LIST_ANY_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
IMPLEMENT_LIST_ANY_VA_2(BM_HEAP, PVRSRV_ERROR, PVRSRV_OK)
@@ -55,6 +77,27 @@ IMPLEMENT_LIST_INSERT(PVRSRV_POWER_DEV)
IMPLEMENT_LIST_REMOVE(PVRSRV_POWER_DEV)
+/*===================================================================
+ BELOW ARE IMPLEMENTED SOME COMMON CALLBACKS USED IN DIFFERENT FILES
+ ===================================================================*/
+
+
+/*!
+******************************************************************************
+ @Function MatchDeviceKM_AnyVaCb
+ @Description Matchs a device node with an id and optionally a class.
+
+ @Input psDeviceNode - Pointer to the device node.
+ @Input va - Variable argument list, with te following values:
+ # ui32DevIndex - Index of de device to match.
+ # bIgnoreClass - Flag indicating if there's
+ no need to check the device class.
+ # eDevClass - Device class, ONLY present if
+ bIgnoreClass was IMG_FALSE.
+
+ @Return The pointer to the device node if it matchs, IMG_NULL
+ otherwise.
+******************************************************************************/
IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
{
IMG_UINT32 ui32DevIndex;
@@ -69,8 +112,9 @@ IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
}
else
{
-
-
+ /*this value will never be used, since the short circuit evaluation
+ of the first clause will stop because bIgnoreClass is true, but the
+ compiler complains if it's not initialized.*/
eDevClass = PVRSRV_DEVICE_CLASS_FORCE_I32;
}
@@ -82,6 +126,20 @@ IMG_VOID* MatchDeviceKM_AnyVaCb(PVRSRV_DEVICE_NODE* psDeviceNode, va_list va)
return IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function MatchPowerDeviceIndex_AnyVaCb
+
+ @Description
+ Matches a power device with its device index.
+
+ @Input va : variable argument list with:
+ ui32DeviceIndex : device index
+
+ @Return the pointer to the device it matched, IMG_NULL otherwise.
+
+******************************************************************************/
IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va)
{
IMG_UINT32 ui32DeviceIndex;
diff --git a/sgx/services4/srvkm/common/mem.c b/sgx/services4/srvkm/common/mem.c
index 5b5d1ac..3f8286b 100644
--- a/sgx/services4/srvkm/common/mem.c
+++ b/sgx/services4/srvkm/common/mem.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title System memory functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description System memory allocation APIs
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "pvr_bridge_km.h"
@@ -47,7 +64,7 @@ FreeSharedSysMemCallBack(IMG_PVOID pvParam,
sizeof(PVRSRV_KERNEL_MEM_INFO),
psKernelMemInfo,
IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
@@ -80,6 +97,9 @@ PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
if(OSAllocPages(psKernelMemInfo->ui32Flags,
psKernelMemInfo->uAllocSize,
(IMG_UINT32)HOST_PAGESIZE(),
+ IMG_NULL,
+ 0,
+ IMG_NULL,
&psKernelMemInfo->pvLinAddrKM,
&psKernelMemInfo->sMemBlk.hOSMemHandle)
!= PVRSRV_OK)
@@ -92,7 +112,7 @@ PVRSRVAllocSharedSysMemoryKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* register with the resman */
psKernelMemInfo->sMemBlk.hResItem =
ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_MEM_INFO,
@@ -151,3 +171,6 @@ PVRSRVDissociateMemFromResmanKM(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
return eError;
}
+/******************************************************************************
+ End of file (mem.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/mem_debug.c b/sgx/services4/srvkm/common/mem_debug.c
index e721fb3..6b49db0 100644
--- a/sgx/services4/srvkm/common/mem_debug.c
+++ b/sgx/services4/srvkm/common/mem_debug.c
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Memory debugging routines.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Adds extra memory to the allocations to trace the memory bounds
+ and other runtime information.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef MEM_DEBUG_C
#define MEM_DEBUG_C
@@ -39,13 +57,17 @@ extern "C"
#define STOP_ON_ERROR 0
-
-
-
-
-
-
-
+ /*
+ Allocated Memory Layout:
+
+ --------- \
+ Status [OSMEM_DEBUG_INFO] |- TEST_BUFFER_PADDING_STATUS
+ --------- <
+ [0xBB]* [raw bytes] |- ui32Size
+ --------- <
+ [0xB2]* [raw bytes] |- TEST_BUFFER_PADDING_AFTER
+ --------- /
+ */
IMG_BOOL MemCheck(const IMG_PVOID pvAddr, const IMG_UINT8 ui8Pattern, IMG_SIZE_T uSize)
{
@@ -60,13 +82,14 @@ extern "C"
return IMG_TRUE;
}
-
-
+ /*
+ This function expects the pointer to the user data, not the debug data.
+ */
IMG_VOID OSCheckMemDebug(IMG_PVOID pvCpuVAddr, IMG_SIZE_T uSize, const IMG_CHAR *pszFileName, const IMG_UINT32 uLine)
{
OSMEM_DEBUG_INFO const *psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32)pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
-
+ /* invalid pointer */
if (pvCpuVAddr == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : null pointer"
@@ -77,7 +100,7 @@ extern "C"
while (STOP_ON_ERROR);
}
-
+ /* align */
if (((IMG_UINT32)pvCpuVAddr&3) != 0)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : invalid alignment"
@@ -88,7 +111,7 @@ extern "C"
while (STOP_ON_ERROR);
}
-
+ /*check guard region before*/
if (!MemCheck((IMG_PVOID)psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore)))
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : guard region before overwritten"
@@ -99,7 +122,7 @@ extern "C"
while (STOP_ON_ERROR);
}
-
+ /*check size*/
if (uSize != psInfo->uSize)
{
PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : supplied size was different to stored size (0x%X != 0x%X)"
@@ -110,7 +133,7 @@ extern "C"
while (STOP_ON_ERROR);
}
-
+ /*check size parity*/
if ((0x01234567 ^ psInfo->uSizeParityCheck) != psInfo->uSize)
{
PVR_DPF((PVR_DBG_WARNING, "Pointer 0x%X : stored size parity error (0x%X != 0x%X)"
@@ -122,11 +145,11 @@ extern "C"
}
else
{
-
+ /*the stored size is ok, so we use it instead the supplied uSize*/
uSize = psInfo->uSize;
}
-
+ /*check padding after*/
if (uSize)
{
if (!MemCheck((IMG_VOID*)((IMG_UINT32)pvCpuVAddr + uSize), 0xB2, TEST_BUFFER_PADDING_AFTER))
@@ -139,7 +162,7 @@ extern "C"
}
}
-
+ /* allocated... */
if (psInfo->eValid != isAllocated)
{
PVR_DPF((PVR_DBG_ERROR, "Pointer 0x%X : not allocated (freed? %d)"
@@ -155,7 +178,7 @@ extern "C"
{
IMG_SIZE_T i = 0;
- for (; i < 128; i++)
+ for (; i < 128; i++) /*changed to 128 to match the filename array size*/
{
*pDest = *pSrc;
if (*pSrc == '\0') break;
@@ -187,11 +210,10 @@ extern "C"
return eError;
}
-
OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + TEST_BUFFER_PADDING_STATUS, 0xBB, ui32Size);
OSMemSet((IMG_CHAR *)(*ppvCpuVAddr) + ui32Size + TEST_BUFFER_PADDING_STATUS, 0xB2, TEST_BUFFER_PADDING_AFTER);
-
+ /*fill the dbg info struct*/
psInfo = (OSMEM_DEBUG_INFO *)(*ppvCpuVAddr);
OSMemSet(psInfo->sGuardRegionBefore, 0xB1, sizeof(psInfo->sGuardRegionBefore));
@@ -201,11 +223,12 @@ extern "C"
psInfo->uSize = ui32Size;
psInfo->uSizeParityCheck = 0x01234567 ^ ui32Size;
-
+ /*point to the user data section*/
*ppvCpuVAddr = (IMG_PVOID) ((IMG_UINT32)*ppvCpuVAddr)+TEST_BUFFER_PADDING_STATUS;
#ifdef PVRSRV_LOG_MEMORY_ALLOCS
-
+ /*this is here to simplify the surounding logging macro, that is a expression
+ maybe the macro should be an expression */
PVR_TRACE(("Allocated pointer (after debug info): 0x%X from %s:%d", *ppvCpuVAddr, pszFilename, ui32Line));
#endif
@@ -221,16 +244,16 @@ extern "C"
{
OSMEM_DEBUG_INFO *psInfo;
-
+ /*check dbginfo (arg pointing to user memory)*/
OSCheckMemDebug(pvCpuVAddr, ui32Size, pszFilename, ui32Line);
-
- OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
+ /*mark memory as freed*/
+ OSMemSet(pvCpuVAddr, 0xBF, ui32Size + TEST_BUFFER_PADDING_AFTER);
-
+ /*point to the starting address of the total allocated memory*/
psInfo = (OSMEM_DEBUG_INFO *)((IMG_UINT32) pvCpuVAddr - TEST_BUFFER_PADDING_STATUS);
-
+ /*update dbg info struct*/
psInfo->uSize = 0;
psInfo->uSizeParityCheck = 0;
psInfo->eValid = isFree;
@@ -245,6 +268,6 @@ extern "C"
}
#endif
-#endif
+#endif /* PVRSRV_DEBUG_OS_MEMORY */
-#endif
+#endif /* MEM_DEBUG_C */
diff --git a/sgx/services4/srvkm/common/metrics.c b/sgx/services4/srvkm/common/metrics.c
index 640eb04..e9f459a 100644
--- a/sgx/services4/srvkm/common/metrics.c
+++ b/sgx/services4/srvkm/common/metrics.c
@@ -1,36 +1,54 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Time measuring functions.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "metrics.h"
+/* VGX: */
#if defined(SUPPORT_VGX)
#include "vgxapi_km.h"
#endif
+/* SGX: */
#if defined(SUPPORT_SGX)
#include "sgxapi_km.h"
#endif
@@ -47,6 +65,13 @@ static volatile IMG_UINT32 *pui32TimerRegister = 0;
Temporal_Data asTimers[PVRSRV_NUM_TIMERS];
+/***********************************************************************************
+ Function Name : PVRSRVTimeNow
+ Inputs : None
+ Outputs : None
+ Returns : Current timer register value
+ Description : Returns the current timer register value
+************************************************************************************/
IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
{
if (!pui32TimerRegister)
@@ -67,14 +92,21 @@ IMG_UINT32 PVRSRVTimeNow(IMG_VOID)
return (0xffffffff-*pui32TimerRegister);
-#else
+#else /* defined(__sh__) */
return 0;
-#endif
+#endif /* defined(__sh__) */
}
+/***********************************************************************************
+ Function Name : PVRSRVGetCPUFreq
+ Inputs : None
+ Outputs : None
+ Returns : CPU timer frequency
+ Description : Returns the CPU timer frequency
+************************************************************************************/
static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
{
IMG_UINT32 ui32Time1, ui32Time2;
@@ -91,6 +123,13 @@ static IMG_UINT32 PVRSRVGetCPUFreq(IMG_VOID)
}
+/***********************************************************************************
+ Function Name : PVRSRVSetupMetricTimers
+ Inputs : pvDevInfo
+ Outputs : None
+ Returns : None
+ Description : Resets metric timers and sets up the timer register
+************************************************************************************/
IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
{
IMG_UINT32 ui32Loop;
@@ -106,29 +145,36 @@ IMG_VOID PVRSRVSetupMetricTimers(IMG_VOID *pvDevInfo)
#if defined(__sh__)
-
-
-
-
+ /* timer control register */
+ // clock / 1024 when TIMER_DIVISOR = 4
+ // underflow int disabled
+ // we get approx 38 uS per timer tick
*TCR_2 = TIMER_DIVISOR;
-
+ /* reset the timer counter to 0 */
*TCOR_2 = *TCNT_2 = (IMG_UINT)0xffffffff;
-
+ /* start timer 2 */
*TST_REG |= (IMG_UINT8)0x04;
pui32TimerRegister = (IMG_UINT32 *)TCNT_2;
- #else
+ #else /* defined(__sh__) */
pui32TimerRegister = 0;
- #endif
+ #endif /* defined(__sh__) */
}
+/***********************************************************************************
+ Function Name : PVRSRVOutputMetricTotals
+ Inputs : None
+ Outputs : None
+ Returns : None
+ Description : Displays final metric data
+************************************************************************************/
IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
{
IMG_UINT32 ui32TicksPerMS, ui32Loop;
@@ -149,12 +195,18 @@ IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID)
}
}
#if 0
-
+ /*
+ ** EXAMPLE TIMER OUTPUT
+ */
PVR_DPF((PVR_DBG_ERROR," Timer(%u): Total = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_TICKS(PVRSRV_TIMER_EXAMPLE_1)));
PVR_DPF((PVR_DBG_ERROR," Timer(%u): Time = %ums",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_TOTAL_IN_MS(PVRSRV_TIMER_EXAMPLE_1)));
PVR_DPF((PVR_DBG_ERROR," Timer(%u): Count = %u",PVRSRV_TIMER_EXAMPLE_1, PVRSRV_TIMER_COUNT(PVRSRV_TIMER_EXAMPLE_1)));
#endif
}
-#endif
+#endif /* defined(DEBUG) || defined(TIMING) */
+
+/******************************************************************************
+ End of file (metrics.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/osfunc_common.c b/sgx/services4/srvkm/common/osfunc_common.c
index e0a46da..99d4928 100644
--- a/sgx/services4/srvkm/common/osfunc_common.c
+++ b/sgx/services4/srvkm/common/osfunc_common.c
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Wrapper layer for osfunc routines that have common code.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Adds extra memory to the allocations to trace the memory bounds
+ and other runtime information.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "img_types.h"
#include "services_headers.h"
diff --git a/sgx/services4/srvkm/common/pdump_common.c b/sgx/services4/srvkm/common/pdump_common.c
index 4d6c429..bb10f03 100644
--- a/sgx/services4/srvkm/common/pdump_common.c
+++ b/sgx/services4/srvkm/common/pdump_common.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Common PDump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if defined(PDUMP)
#include <stdarg.h>
@@ -30,13 +46,16 @@
#include "services_headers.h"
#include "perproc.h"
+/* pdump headers */
#include "pdump_km.h"
#include "pdump_int.h"
+/* Allow temporary buffer size override */
#if !defined(PDUMP_TEMP_BUFFER_SIZE)
#define PDUMP_TEMP_BUFFER_SIZE (64 * 1024U)
#endif
+/* DEBUG */
#if 1
#define PDUMP_DBG(a) PDumpOSDebugPrintf (a)
#else
@@ -53,6 +72,7 @@ static IMG_HANDLE ghTempBufferBlockAlloc;
static IMG_UINT16 gui16MMUContextUsage = 0;
#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
IMG_UINT32 g_ui32EveryLineCounter = 1U;
#endif
@@ -66,7 +86,7 @@ IMG_BOOL _PDumpIsPersistent(IMG_VOID)
if(psPerProc == IMG_NULL)
{
-
+ /* only occurs early in driver init, and init phase is already persistent */
return IMG_FALSE;
}
return psPerProc->bPDumpPersistent;
@@ -81,13 +101,15 @@ IMG_BOOL _PDumpIsProcessActive(IMG_VOID)
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc == IMG_NULL)
{
-
+ /* FIXME: kernel process logs some comments when kernel module is
+ * loaded, want to keep those.
+ */
return IMG_TRUE;
}
return psPerProc->bPDumpActive;
}
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
#if defined(PDUMP_DEBUG_OUTFILES)
static INLINE
@@ -96,16 +118,30 @@ IMG_UINT32 _PDumpGetPID(IMG_VOID)
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc == IMG_NULL)
{
-
+ /* Kernel PID */
return 0;
}
return psPerProc->ui32PID;
}
-#endif
-
+#endif /* PDUMP_DEBUG_OUTFILES */
+
+/**************************************************************************
+ * Function Name : GetTempBuffer
+ * Inputs : None
+ * Outputs : None
+ * Returns : Temporary buffer address, or IMG_NULL
+ * Description : Get temporary buffer address.
+**************************************************************************/
static IMG_VOID *GetTempBuffer(IMG_VOID)
{
-
+ /*
+ * Allocate the temporary buffer, it it hasn't been allocated already.
+ * Return the address of the temporary buffer, or IMG_NULL if it
+ * couldn't be allocated.
+ * It is expected that the buffer will be allocated once, at driver
+ * load time, and left in place until the driver unloads.
+ */
+
if (gpvTempBuffer == IMG_NULL)
{
PVRSRV_ERROR eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
@@ -144,19 +180,19 @@ static IMG_VOID FreeTempBuffer(IMG_VOID)
IMG_VOID PDumpInitCommon(IMG_VOID)
{
-
+ /* Allocate temporary buffer for copying from user space */
(IMG_VOID) GetTempBuffer();
-
+ /* Call environment specific PDump initialisation */
PDumpInit();
}
IMG_VOID PDumpDeInitCommon(IMG_VOID)
{
-
+ /* Free temporary buffer */
FreeTempBuffer();
-
+ /* Call environment specific PDump Deinitialisation */
PDumpDeInit();
}
@@ -191,6 +227,13 @@ PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame)
#endif
}
+/**************************************************************************
+ * Function Name : PDumpRegWithFlagsKM
+ * Inputs : pszPDumpDevName, Register offset, and value to write
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Create a PDUMP string, which represents a register write
+**************************************************************************/
PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data,
@@ -211,6 +254,13 @@ PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpRegKM
+ * Inputs : Register offset, and value to write
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Create a PDUMP string, which represents a register write
+**************************************************************************/
PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data)
@@ -218,6 +268,18 @@ PVRSRV_ERROR PDumpRegKM(IMG_CHAR *pszPDumpRegName,
return PDumpRegWithFlagsKM(pszPDumpRegName, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS);
}
+/**************************************************************************
+ * Function Name : PDumpRegPolWithFlagsKM
+ * Inputs : Description of what this register read is trying to do
+ * pszPDumpDevName
+ * Register offset
+ * expected value
+ * mask for that value
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents a register read
+ * with the expected value
+**************************************************************************/
PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32RegAddr,
IMG_UINT32 ui32RegValue,
@@ -225,7 +287,7 @@ PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32Flags,
PDUMP_POLL_OPERATOR eOperator)
{
-
+ /* Timings correct for linux and XP */
#define POLL_DELAY 1000U
#define POLL_COUNT_LONG (2000000000U / POLL_DELAY)
#define POLL_COUNT_SHORT (1000000U / POLL_DELAY)
@@ -237,25 +299,11 @@ PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
PDUMP_DBG(("PDumpRegPolWithFlagsKM"));
if ( _PDumpIsPersistent() )
{
-
+ /* Don't pdump-poll if the process is persistent */
return PVRSRV_OK;
}
-#if 0
- if (((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
- (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_TA_FINISHED_MASK) != 0) ||
- ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
- (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_PIXELBE_END_RENDER_MASK) != 0) ||
- ((ui32RegAddr == EUR_CR_EVENT_STATUS) &&
- (ui32RegValue & ui32Mask & EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK) != 0))
- {
- ui32PollCount = POLL_COUNT_LONG;
- }
- else
-#endif
- {
- ui32PollCount = POLL_COUNT_LONG;
- }
+ ui32PollCount = POLL_COUNT_LONG;
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "POL :%s:0x%08X 0x%08X 0x%08X %d %u %d\r\n",
pszPDumpRegName, ui32RegAddr, ui32RegValue,
@@ -270,11 +318,38 @@ PVRSRV_ERROR PDumpRegPolWithFlagsKM(IMG_CHAR *pszPDumpRegName,
}
+/**************************************************************************
+ * Function Name : PDumpRegPol
+ * Inputs : Description of what this register read is trying to do
+ * pszPDumpDevName
+ Register offset
+ * expected value
+ * mask for that value
+ * Outputs : None
+ * Returns : None
+ * Description : Create a PDUMP string which represents a register read
+ * with the expected value
+**************************************************************************/
PVRSRV_ERROR PDumpRegPolKM(IMG_CHAR *pszPDumpRegName, IMG_UINT32 ui32RegAddr, IMG_UINT32 ui32RegValue, IMG_UINT32 ui32Mask, PDUMP_POLL_OPERATOR eOperator)
{
return PDumpRegPolWithFlagsKM(pszPDumpRegName, ui32RegAddr, ui32RegValue, ui32Mask, PDUMP_FLAGS_CONTINUOUS, eOperator);
}
+/**************************************************************************
+ * Function Name : PDumpMallocPages
+ * Inputs : psDevID, ui32DevVAddr, pvLinAddr, ui32NumBytes, hOSMemHandle
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Malloc memory pages
+
+FIXME: This function assumes pvLinAddr is the address of the start of the
+block for this hOSMemHandle.
+If this isn't true, the call to PDumpOSCPUVAddrToDevPAddr below will be
+incorrect. (Consider using OSMemHandleToCPUPAddr() instead?)
+The only caller at the moment is in buffer_manager.c, which does the right
+thing.
+**************************************************************************/
PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
IMG_UINT32 ui32DevVAddr,
IMG_CPU_VIRTADDR pvLinAddr,
@@ -294,14 +369,14 @@ PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
PDUMP_GET_SCRIPT_STRING();
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Always dump physical pages backing a shared allocation */
ui32Flags |= ( _PDumpIsPersistent() || bShared ) ? PDUMP_FLAGS_PERSISTENT : 0;
#else
PVR_UNREFERENCED_PARAMETER(bShared);
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* However, lin addr is only required in non-linux OSes */
#if !defined(LINUX)
PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & HOST_PAGEMASK) == 0);
#endif
@@ -309,8 +384,9 @@ PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
PVR_ASSERT(((IMG_UINT32) ui32DevVAddr & HOST_PAGEMASK) == 0);
PVR_ASSERT(((IMG_UINT32) ui32NumBytes & HOST_PAGEMASK) == 0);
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the memory allocation
+ */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- MALLOC :%s:VA_%08X 0x%08X %u\r\n",
psDevID->pszPDumpDevName, ui32DevVAddr, ui32NumBytes, ui32PageSize);
if(eErr != PVRSRV_OK)
@@ -319,8 +395,9 @@ PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
pui8LinAddr = (IMG_PUINT8) pvLinAddr;
ui32Offset = 0;
ui32NumPages = ui32NumBytes / ui32PageSize;
@@ -328,16 +405,11 @@ PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
{
ui32NumPages--;
-
-
-
-
-
-
-
-
-
-
+ /* See FIXME in function header.
+ * Currently: linux pdump uses OSMemHandle and Offset
+ * other OSes use the LinAddr.
+ */
+ /* Calculate the device physical address for this page */
PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
hOSMemHandle,
ui32Offset,
@@ -345,7 +417,7 @@ PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
ui32PageSize,
&sDevPAddr);
ui32Page = (IMG_UINT32)(sDevPAddr.uiAddr / ui32PageSize);
-
+ /* increment kernel virtual address */
pui8LinAddr += ui32PageSize;
ui32Offset += ui32PageSize;
@@ -366,6 +438,13 @@ PVRSRV_ERROR PDumpMallocPages (PVRSRV_DEVICE_IDENTIFIER *psDevID,
}
+/**************************************************************************
+ * Function Name : PDumpMallocPageTable
+ * Inputs : psDevId, pvLinAddr, ui32NumBytes, hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Malloc memory page table
+**************************************************************************/
PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
@@ -383,8 +462,9 @@ PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the memory allocation
+ */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLen,
"-- MALLOC :%s:PAGE_TABLE 0x%08X %u\r\n",
@@ -397,15 +477,16 @@ PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
-
-
-
-
+ /*
+ Write to the MMU script stream indicating the memory allocation
+ */
+ // FIXME: we'll never need more than a 4k page for a pagetable
+ // fixing to 1 page for now.
+ // note: when the mmu code supports packed pagetables the PTs
+ // will be as small as 16bytes
PDumpOSCPUVAddrToDevPAddr(psDevId->eDeviceType,
- hOSMemHandle,
+ hOSMemHandle, /* um - does this mean the pvLinAddr would be ignored? Is that safe? */
ui32Offset,
(IMG_PUINT8) pvLinAddr,
ui32PTSize,
@@ -415,8 +496,8 @@ PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
psDevId->pszPDumpDevName,
(IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag,
sDevPAddr.uiAddr,
- ui32PTSize,
- ui32PTSize,
+ ui32PTSize,//size
+ ui32PTSize,//alignment
sDevPAddr.uiAddr);
if(eErr != PVRSRV_OK)
{
@@ -427,12 +508,21 @@ PVRSRV_ERROR PDumpMallocPageTable (PVRSRV_DEVICE_IDENTIFIER *psDevId,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpFreePages
+ * Inputs : psBMHeap, sDevVAddr, ui32NumBytes, hUniqueTag,
+ bInterLeaved
+ * Outputs : None
+ * Returns : None
+ * Description : Free memory pages
+**************************************************************************/
PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_UINT32 ui32NumBytes,
IMG_UINT32 ui32PageSize,
IMG_HANDLE hUniqueTag,
- IMG_BOOL bInterleaved)
+ IMG_BOOL bInterleaved,
+ IMG_BOOL bSparse)
{
PVRSRV_ERROR eErr;
IMG_UINT32 ui32NumPages, ui32PageCounter;
@@ -448,8 +538,9 @@ PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
-
+ /*
+ Write a comment to the PDUMP2 script streams indicating the memory free
+ */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:VA_%08X\r\n",
psDeviceNode->sDevId.pszPDumpDevName, sDevVAddr.uiAddr);
if(eErr != PVRSRV_OK)
@@ -458,7 +549,9 @@ PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* if we're dumping a shared heap, need to ensure phys allocation
+ * is freed even if this app isn't the one marked for pdumping
+ */
{
PVRSRV_DEVICE_NODE *psDeviceNode = psBMHeap->pBMContext->psDeviceNode;
@@ -470,8 +563,9 @@ PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
#endif
PDumpOSWriteString2(hScript, ui32Flags);
-
-
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
ui32NumPages = ui32NumBytes / ui32PageSize;
for (ui32PageCounter = 0; ui32PageCounter < ui32NumPages; ui32PageCounter++)
{
@@ -479,7 +573,13 @@ PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
{
sDevPAddr = psDeviceNode->pfnMMUGetPhysPageAddr(psBMHeap->pMMUHeap, sDevVAddr);
- PVR_ASSERT(sDevPAddr.uiAddr != 0)
+ /* With sparse mappings we expect spaces */
+ if (bSparse && (sDevPAddr.uiAddr == 0))
+ {
+ continue;
+ }
+
+ PVR_ASSERT(sDevPAddr.uiAddr != 0);
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "FREE :%s:PA_%08X%08X\r\n",
psDeviceNode->sDevId.pszPDumpDevName, (IMG_UINT32)(IMG_UINTPTR_T)hUniqueTag, sDevPAddr.uiAddr);
@@ -491,7 +591,7 @@ PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
}
else
{
-
+ /* Gap pages in an interleaved allocation should be ignored. */
}
sDevVAddr.uiAddr += ui32PageSize;
@@ -499,6 +599,13 @@ PVRSRV_ERROR PDumpFreePages (BM_HEAP *psBMHeap,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpFreePageTable
+ * Inputs : psDevID, pvLinAddr, ui32NumBytes, hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Free memory page table
+**************************************************************************/
PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
@@ -515,11 +622,12 @@ PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
-
- PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0);
-
-
+ /* override QAC warning about wrap around */
+ PVR_ASSERT(((IMG_UINTPTR_T)pvLinAddr & (ui32PTSize-1UL)) == 0); /* PRQA S 3382 */
+ /*
+ Write a comment to the PDUMP2 script streams indicating the memory free
+ */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "-- FREE :%s:PAGE_TABLE\r\n", psDevID->pszPDumpDevName);
if(eErr != PVRSRV_OK)
{
@@ -527,15 +635,16 @@ PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
-
-
-
-
+ /*
+ Write to the MMU script stream indicating the memory free
+ */
+ // FIXME: we'll never need more than a 4k page for a pagetable
+ // fixing to 1 page for now.
+ // note: when the mmu code supports packed pagetables the PTs
+ // will be as small as 16bytes
PDumpOSCPUVAddrToDevPAddr(psDevID->eDeviceType,
- hOSMemHandle,
+ hOSMemHandle, /* um - does this mean the pvLinAddr would be ignored? Is that safe? */
0,
(IMG_PUINT8) pvLinAddr,
ui32PTSize,
@@ -556,6 +665,18 @@ PVRSRV_ERROR PDumpFreePageTable (PVRSRV_DEVICE_IDENTIFIER *psDevID,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpPDRegWithFlags
+ * Inputs : psMMUAttrib
+ * : ui32Reg
+ * : ui32Data
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : None
+ * Description : Kernel Services internal pdump memory API
+ * Used for registers specifying physical addresses
+ e.g. MMU page directory register
+**************************************************************************/
PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data,
@@ -575,8 +696,9 @@ PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
pszRegString = psMMUAttrib->sDevId.pszPDumpRegName;
}
-
-
+ /*
+ Write to the MMU script stream indicating the physical page directory
+ */
#if defined(SGX_FEATURE_36BIT_MMU)
eErr = PDumpOSBufprintf(hScript, ui32MaxLen,
"WRW :%s:$1 :%s:PA_%08X%08X:0x0\r\n",
@@ -626,6 +748,18 @@ PVRSRV_ERROR PDumpPDRegWithFlags(PDUMP_MMU_ATTRIB *psMMUAttrib,
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpPDReg
+ * Inputs : psMMUAttrib
+ : ui32Reg
+ * : ui32Data
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Kernel Services internal pdump memory API
+ * Used for registers specifying physical addresses
+ e.g. MMU page directory register
+**************************************************************************/
PVRSRV_ERROR PDumpPDReg (PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_UINT32 ui32Reg,
IMG_UINT32 ui32Data,
@@ -634,6 +768,19 @@ PVRSRV_ERROR PDumpPDReg (PDUMP_MMU_ATTRIB *psMMUAttrib,
return PDumpPDRegWithFlags(psMMUAttrib, ui32Reg, ui32Data, PDUMP_FLAGS_CONTINUOUS, hUniqueTag);
}
+/**************************************************************************
+ * Function Name : PDumpMemPolKM
+ * Inputs : psMemInfo
+ * : ui32Offset
+ * : ui32Value
+ * : ui32Mask
+ * : eOperator
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Implements Client pdump memory poll API
+**************************************************************************/
PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_UINT32 ui32Offset,
IMG_UINT32 ui32Value,
@@ -661,17 +808,18 @@ PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
if ( _PDumpIsPersistent() )
{
-
+ /* Don't pdump-poll if the process is persistent */
return PVRSRV_OK;
}
-
+ /* Check the offset and size don't exceed the bounds of the allocation */
PVR_ASSERT((ui32Offset + sizeof(IMG_UINT32)) <= psMemInfo->uAllocSize);
psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the virtual memory pol
+ */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLen,
"-- POL :%s:VA_%08X 0x%08X 0x%08X %d %d %d\r\n",
@@ -691,27 +839,28 @@ PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
pui8LinAddr = psMemInfo->pvLinAddrKM;
-
+ /* Advance address by offset */
pui8LinAddr += ui32Offset;
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
ui32Offset,
pui8LinAddr,
psMMUAttrib->ui32DataPageMask,
&ui32PageOffset);
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = psMemInfo->sDevVAddr.uiAddr + ui32Offset - ui32PageOffset;
PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageOffset;
eErr = PDumpOSBufprintf(hScript,
@@ -735,12 +884,23 @@ PVRSRV_ERROR PDumpMemPolKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
return PVRSRV_OK;
}
-PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
- PVRSRV_KERNEL_MEM_INFO *psMemInfo,
- IMG_UINT32 ui32Offset,
- IMG_UINT32 ui32Bytes,
- IMG_UINT32 ui32Flags,
- IMG_HANDLE hUniqueTag)
+/**************************************************************************
+ * Function Name : _PDumpMemIntKM
+ * Inputs : psMemInfo
+ * : ui32Offset
+ * : ui32Bytes
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Implements Client pdump mem API
+**************************************************************************/
+static PVRSRV_ERROR _PDumpMemIntKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
{
PVRSRV_ERROR eErr;
IMG_UINT32 ui32NumPages;
@@ -757,7 +917,7 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
PDUMP_GET_SCRIPT_AND_FILE_STRING();
-
+ /* PRQA S 3415 1 */ /* side effects desired */
if (ui32Bytes == 0 || PDumpOSIsSuspended())
{
return PVRSRV_OK;
@@ -765,8 +925,9 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
psMMUAttrib = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
-
-
+ /*
+ check the offset and size don't exceed the bounds of the allocation
+ */
PVR_ASSERT((ui32Offset + ui32Bytes) <= psMemInfo->uAllocSize);
if (!PDumpOSJTInitialised())
@@ -775,7 +936,9 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* if we're dumping a shared heap, need to ensure phys allocation
+ * is initialised even if this app isn't the one marked for pdumping
+ */
{
BM_HEAP *pHeap = ((BM_BUF*)psMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap;
PVRSRV_DEVICE_NODE *psDeviceNode = pHeap->pBMContext->psDeviceNode;
@@ -787,7 +950,7 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
}
#endif
-
+ /* setup memory addresses */
if(pvAltLinAddr)
{
pui8DataLinAddr = pvAltLinAddr;
@@ -799,7 +962,7 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
pui8LinAddr = (IMG_UINT8 *)psMemInfo->pvLinAddrKM;
sDevVAddr = psMemInfo->sDevVAddr;
-
+ /* advance address by offset */
sDevVAddr.uiAddr += ui32Offset;
pui8LinAddr += ui32Offset;
@@ -809,8 +972,9 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
-
-
+ /*
+ write the binary data up-front.
+ */
if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
pui8DataLinAddr,
ui32Bytes,
@@ -832,8 +996,9 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
return eErr;
}
-
-
+ /*
+ Write a comment to the PDump2 script streams indicating the virtual memory load
+ */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLenScript,
"-- LDB :%s:VA_%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
@@ -850,9 +1015,10 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
}
PDumpOSWriteString2(hScript, ui32Flags);
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
PDumpOSCPUVAddrToPhysPages(psMemInfo->sMemBlk.hOSMemHandle,
ui32Offset,
pui8LinAddr,
@@ -865,30 +1031,30 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
{
ui32NumPages--;
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageByteOffset;
if (ui32DataPageSize <= PDUMP_TEMP_BUFFER_SIZE)
{
-
+ /* if a page fits within temp buffer, we should dump in page-aligned chunks. */
PVR_ASSERT((sDevVPageAddr.uiAddr & psMMUAttrib->ui32DataPageMask) == 0);
}
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageByteOffset;
-
+ /* how many bytes to dump from this page */
if (ui32PageByteOffset + ui32Bytes > ui32DataPageSize)
{
-
+ /* dump up to the page boundary */
ui32BlockBytes = ui32DataPageSize - ui32PageByteOffset;
}
else
{
-
+ /* dump what's left */
ui32BlockBytes = ui32Bytes;
}
@@ -908,28 +1074,68 @@ PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
}
PDumpOSWriteString2(hScript, ui32Flags);
-
+ /* update details for next page */
#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
-
+ /* page may be larger than pdump temporary buffer */
ui32PageByteOffset = (ui32PageByteOffset + ui32BlockBytes) % ui32DataPageSize;
#else
-
+ /* page offset 0 after first page dump */
ui32PageByteOffset = 0;
#endif
-
- ui32Bytes -= ui32BlockBytes;
-
+ /* bytes left over */
+ ui32Bytes -= ui32BlockBytes; /* PRQA S 3382 */ /* QAC missed MIN test */
+ /* advance devVaddr */
sDevVAddr.uiAddr += ui32BlockBytes;
-
+ /* advance the cpuVaddr */
pui8LinAddr += ui32BlockBytes;
-
+ /* update the file write offset */
ui32ParamOutPos += ui32BlockBytes;
}
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpMemKM
+ * Inputs : psMemInfo
+ * : ui32Offset
+ * : ui32Bytes
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Implements Client pdump mem API
+**************************************************************************/
+PVRSRV_ERROR PDumpMemKM(IMG_PVOID pvAltLinAddr,
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32Offset,
+ IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32Flags,
+ IMG_HANDLE hUniqueTag)
+{
+ /*
+ For now we don't support dumping sparse allocations that
+ are from within the kernel, or are from UM but without a
+ alternative linear address
+ */
+ PVR_ASSERT((psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE) == 0);
+
+ if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
+ {
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+ else
+ {
+ return _PDumpMemIntKM(pvAltLinAddr,
+ psMemInfo,
+ ui32Offset,
+ ui32Bytes,
+ ui32Flags,
+ hUniqueTag);
+ }
+}
+
PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
@@ -941,7 +1147,7 @@ PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
{
PDUMP_MMU_ATTRIB sMMUAttrib;
-
+ /* Override the (variable) PT size since PDs are always 4K in size */
sMMUAttrib = *psMMUAttrib;
sMMUAttrib.ui32PTSize = (IMG_UINT32)HOST_PAGESIZE();
return PDumpMemPTEntriesKM( &sMMUAttrib,
@@ -954,6 +1160,23 @@ PVRSRV_ERROR PDumpMemPDEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
hUniqueTag2);
}
+/**************************************************************************
+ * Function Name : PDumpMemPTEntriesKM
+ * Inputs : psMMUAttrib - MMU attributes for pdump
+ * : pvLinAddr - CPU address of PT base
+ * : ui32Bytes - size
+ * : ui32Flags - pdump flags
+ * : bInitialisePages - whether to initialise pages from file
+ * : hUniqueTag1 - ID for PT physical page
+ * : hUniqueTag2 - ID for target physical page (if !bInitialisePages)
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Kernel Services internal pdump memory API
+ * Used for memory without DevVAddress mappings
+ e.g. MMU page tables
+ FIXME: This function doesn't support non-4k data pages,
+ e.g. dummy data page
+**************************************************************************/
PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
@@ -972,7 +1195,7 @@ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_CPU_PHYADDR sCpuPAddr;
IMG_UINT32 ui32Offset;
IMG_UINT32 ui32ParamOutPos;
- IMG_UINT32 ui32PageMask;
+ IMG_UINT32 ui32PageMask; /* mask for the physical page backing the PT */
PDUMP_GET_SCRIPT_AND_FILE_STRING();
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
@@ -998,9 +1221,10 @@ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
if (bInitialisePages)
{
-
-
-
+ /*
+ write the binary data up-front
+ Use the 'continuous' memory stream
+ */
if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
pvLinAddr,
ui32Bytes,
@@ -1023,16 +1247,18 @@ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
}
}
-
-
-
-
-
+ /*
+ Mask for the physical page address backing the PT
+ The PT size can be less than 4k with variable page size support
+ The PD size is always 4k
+ FIXME: This won't work for dumping the dummy data page
+ */
ui32PageMask = psMMUAttrib->ui32PTSize - 1;
-
-
-
+ /*
+ Write to the MMU script stream indicating the physical page table entries
+ */
+ /* physical pages that back the virtual address */
ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)pvLinAddr & (psMMUAttrib->ui32PTSize - 1));
ui32NumPages = (ui32PageOffset + ui32Bytes + psMMUAttrib->ui32PTSize - 1) / psMMUAttrib->ui32PTSize;
pui8LinAddr = (IMG_UINT8*) pvLinAddr;
@@ -1040,29 +1266,31 @@ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
while (ui32NumPages)
{
ui32NumPages--;
-
-
-
-
-
-
+ /* FIXME: if we used OSMemHandleToCPUPAddr() here, we might be
+ able to lose the lin addr arg. At least one thing that
+ would need to be done here is to pass in an offset, as the
+ calling function doesn't necessarily give us the lin addr
+ of the start of the mem area. Probably best to keep the
+ lin addr arg for now - but would be nice to remove the
+ redundancy */
sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
sDevPAddr = SysCpuPAddrToDevPAddr(psMMUAttrib->sDevId.eDeviceType, sCpuPAddr);
-
+ /* how many bytes to dump from this page */
if (ui32PageOffset + ui32Bytes > psMMUAttrib->ui32PTSize)
{
-
+ /* dump up to the page boundary */
ui32BlockBytes = psMMUAttrib->ui32PTSize - ui32PageOffset;
}
else
{
-
+ /* dump what's left */
ui32BlockBytes = ui32Bytes;
}
-
-
+ /*
+ Write a comment to the MMU script stream indicating the page table load
+ */
if (bInitialisePages)
{
@@ -1086,11 +1314,11 @@ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
{
for (ui32Offset = 0; ui32Offset < ui32BlockBytes; ui32Offset += sizeof(IMG_UINT32))
{
- IMG_UINT32 ui32PTE = *((IMG_UINT32 *)(IMG_UINTPTR_T)(pui8LinAddr + ui32Offset));
+ IMG_UINT32 ui32PTE = *((IMG_UINT32 *)(IMG_UINTPTR_T)(pui8LinAddr + ui32Offset)); /* PRQA S 3305 */ /* strict pointer */
if ((ui32PTE & psMMUAttrib->ui32PDEMask) != 0)
{
-
+ /* PT entry points to non-null page */
#if defined(SGX_FEATURE_36BIT_MMU)
eErr = PDumpOSBufprintf(hScript,
ui32MaxLenScript,
@@ -1176,15 +1404,15 @@ PVRSRV_ERROR PDumpMemPTEntriesKM(PDUMP_MMU_ATTRIB *psMMUAttrib,
}
}
-
+ /* update details for next page */
-
+ /* page offset 0 after first page dump */
ui32PageOffset = 0;
-
+ /* bytes left over */
ui32Bytes -= ui32BlockBytes;
-
+ /* advance the cpuVaddr */
pui8LinAddr += ui32BlockBytes;
-
+ /* update the file write offset */
ui32ParamOutPos += ui32BlockBytes;
}
@@ -1205,7 +1433,7 @@ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_UINT32 ui32Flags = PDUMP_FLAGS_CONTINUOUS;
IMG_UINT32 ui32ParamOutPos;
PDUMP_MMU_ATTRIB *psMMUAttrib;
- IMG_UINT32 ui32PageMask;
+ IMG_UINT32 ui32PageMask; /* mask for the physical page backing the PT */
PDUMP_GET_SCRIPT_AND_FILE_STRING();
@@ -1219,7 +1447,7 @@ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
ui32ParamOutPos = PDumpOSGetStreamOffset(PDUMP_STREAM_PARAM2);
-
+ /* Write the PD phys addr to the param stream up front */
if(!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_PARAM2),
(IMG_UINT8 *)&sPDDevPAddr,
sizeof(IMG_DEV_PHYADDR),
@@ -1241,7 +1469,9 @@ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
return eErr;
}
-
+ /* Write a comment indicating the PD phys addr write, so that the offsets
+ * into the param stream increase in correspondence with the number of bytes
+ * written. */
eErr = PDumpOSBufprintf(hScript,
ui32MaxLenScript,
"-- LDB :%s:PA_0x%08X%08X:0x%08X 0x%08X 0x%08X %s\r\n",
@@ -1258,7 +1488,6 @@ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
}
PDumpOSWriteString2(hScript, ui32Flags);
-
sDevVAddr = psMemInfo->sDevVAddr;
ui32PageByteOffset = sDevVAddr.uiAddr & ui32PageMask;
@@ -1368,13 +1597,17 @@ PVRSRV_ERROR PDumpPDDevPAddrKM(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
return PVRSRV_OK;
}
-
-
-
+/**************************************************************************
+ * Function Name : PDumpCommentKM
+ * Inputs : pszComment, ui32Flags
+ * Outputs : None
+ * Returns : None
+ * Description : Dumps a comment
+**************************************************************************/
PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
{
PVRSRV_ERROR eErr;
- IMG_CHAR pszCommentPrefix[] = "-- ";
+ IMG_CHAR pszCommentPrefix[] = "-- "; /* prefix for comments */
#if defined(PDUMP_DEBUG_OUTFILES)
IMG_CHAR pszTemp[256];
#endif
@@ -1382,17 +1615,19 @@ PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
PDUMP_GET_SCRIPT_STRING();
PDUMP_DBG(("PDumpCommentKM"));
#if defined(PDUMP_DEBUG_OUTFILES)
-
+ /* include comments in the "extended" init phase.
+ * default is to ignore them.
+ */
ui32Flags |= ( _PDumpIsPersistent() ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* Put \r \n sequence at the end if it isn't already there */
PDumpOSVerifyLineEnding(pszComment, ui32MaxLen);
-
+ /* Length of string excluding terminating NULL character */
ui32LenCommentPrefix = PDumpOSBuflen(pszCommentPrefix, sizeof(pszCommentPrefix));
-
-
+ /* Ensure output file is available for writing */
+ /* FIXME: is this necessary? */
if (!PDumpOSWriteString(PDumpOSGetStream(PDUMP_STREAM_SCRIPT2),
(IMG_UINT8*)pszCommentPrefix,
ui32LenCommentPrefix,
@@ -1425,13 +1660,13 @@ PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
}
#if defined(PDUMP_DEBUG_OUTFILES)
-
+ /* Prefix comment with PID and line number */
eErr = PDumpOSSprintf(pszTemp, 256, "%d-%d %s",
_PDumpGetPID(),
g_ui32EveryLineCounter,
pszComment);
-
+ /* Append the comment to the script stream */
eErr = PDumpOSBufprintf(hScript, ui32MaxLen, "%s",
pszTemp);
#else
@@ -1447,14 +1682,22 @@ PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags)
return PVRSRV_OK;
}
-
+/**************************************************************************
+ * Function Name : PDumpCommentWithFlags
+ * Inputs : psPDev - PDev for PDump device
+ * : pszFormat - format string for comment
+ * : ... - args for format string
+ * Outputs : None
+ * Returns : None
+ * Description : PDumps a comments
+**************************************************************************/
PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, ...)
{
PVRSRV_ERROR eErr;
PDUMP_va_list ap;
PDUMP_GET_MSG_STRING();
-
+ /* Construct the string */
PDUMP_va_start(ap, pszFormat);
eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
PDUMP_va_end(ap);
@@ -1466,13 +1709,22 @@ PVRSRV_ERROR PDumpCommentWithFlags(IMG_UINT32 ui32Flags, IMG_CHAR * pszFormat, .
return PDumpCommentKM(pszMsg, ui32Flags);
}
+/**************************************************************************
+ * Function Name : PDumpComment
+ * Inputs : psPDev - PDev for PDump device
+ * : pszFormat - format string for comment
+ * : ... - args for format string
+ * Outputs : None
+ * Returns : None
+ * Description : PDumps a comments
+**************************************************************************/
PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
{
PVRSRV_ERROR eErr;
PDUMP_va_list ap;
PDUMP_GET_MSG_STRING();
-
+ /* Construct the string */
PDUMP_va_start(ap, pszFormat);
eErr = PDumpOSVSprintf(pszMsg, ui32MaxLen, pszFormat, ap);
PDUMP_va_end(ap);
@@ -1484,20 +1736,27 @@ PVRSRV_ERROR PDumpComment(IMG_CHAR *pszFormat, ...)
return PDumpCommentKM(pszMsg, PDUMP_FLAGS_CONTINUOUS);
}
+/**************************************************************************
+ * Function Name : PDumpDriverInfoKM
+ * Inputs : pszString, ui32Flags
+ * Outputs : None
+ * Returns : None
+ * Description : Dumps a comment
+**************************************************************************/
PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
{
PVRSRV_ERROR eErr;
IMG_UINT32 ui32MsgLen;
PDUMP_GET_MSG_STRING();
-
+ /* Construct the string */
eErr = PDumpOSSprintf(pszMsg, ui32MaxLen, "%s", pszString);
if(eErr != PVRSRV_OK)
{
return eErr;
}
-
+ /* Put \r \n sequence at the end if it isn't already there */
PDumpOSVerifyLineEnding(pszMsg, ui32MaxLen);
ui32MsgLen = PDumpOSBuflen(pszMsg, ui32MaxLen);
@@ -1518,6 +1777,30 @@ PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PDumpBitmapKM
+
+ @Description
+
+ Dumps a bitmap from device memory to a file
+
+ @Input psDevId
+ @Input pszFileName
+ @Input ui32FileOffset
+ @Input ui32Width
+ @Input ui32Height
+ @Input ui32StrideInBytes
+ @Input sDevBaseAddr
+ @Input ui32Size
+ @Input ePixelFormat
+ @Input eMemFormat
+ @Input ui32PDumpFlags
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR PDumpBitmapKM( PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
@@ -1543,7 +1826,7 @@ PVRSRV_ERROR PDumpBitmapKM( PVRSRV_DEVICE_NODE *psDeviceNode,
PDumpCommentWithFlags(ui32PDumpFlags, "\r\n-- Dump bitmap of render\r\n");
-
+ /* find MMU context ID */
ui32MMUContextID = psDeviceNode->pfnMMUGetContextID( hDevMemContext );
eErr = PDumpOSBufprintf(hScript,
@@ -1570,6 +1853,25 @@ PVRSRV_ERROR PDumpBitmapKM( PVRSRV_DEVICE_NODE *psDeviceNode,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PDumpReadRegKM
+
+ @Description
+
+ Dumps a read from a device register to a file
+
+ @Input psConnection : connection info
+ @Input pszFileName
+ @Input ui32FileOffset
+ @Input ui32Address
+ @Input ui32Size
+ @Input ui32PDumpFlags
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR PDumpReadRegKM ( IMG_CHAR *pszPDumpRegName,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
@@ -1599,12 +1901,19 @@ PVRSRV_ERROR PDumpReadRegKM ( IMG_CHAR *pszPDumpRegName,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpTestNextFrame
+ @brief Tests whether the next frame will be pdumped
+ @param ui32CurrentFrame
+ @return bFrameDumped
+*****************************************************************************/
IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
{
IMG_BOOL bFrameDumped;
-
-
+ /*
+ Try dumping a string
+ */
(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame + 1);
bFrameDumped = PDumpIsCaptureFrameKM();
(IMG_VOID) PDumpSetFrameKM(ui32CurrentFrame);
@@ -1612,6 +1921,16 @@ IMG_BOOL PDumpTestNextFrame(IMG_UINT32 ui32CurrentFrame)
return bFrameDumped;
}
+/*****************************************************************************
+ @name PDumpSignatureRegister
+ @brief Dumps a single signature register
+ @param psDevId - device ID
+ @param ui32Address - The register address
+ @param ui32Size - The amount of data to be dumped in bytes
+ @param pui32FileOffset - Offset of dump in output file
+ @param ui32Flags - Flags
+ @return none
+*****************************************************************************/
static PVRSRV_ERROR PDumpSignatureRegister (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32Address,
@@ -1639,6 +1958,18 @@ static PVRSRV_ERROR PDumpSignatureRegister (PVRSRV_DEVICE_IDENTIFIER *psDevId,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpRegisterRange
+ @brief Dumps a list of signature registers to a file
+ @param psDevId - device ID
+ @param pszFileName - target filename for dump
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @param pui32FileOffset - file offset
+ @param ui32Size - size of write in bytes
+ @param ui32Flags - pdump flags
+ @return none
+ *****************************************************************************/
static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 *pui32Registers,
@@ -1654,6 +1985,14 @@ static IMG_VOID PDumpRegisterRange(PVRSRV_DEVICE_IDENTIFIER *psDevId,
}
}
+/*****************************************************************************
+ @name PDump3DSignatureRegisters
+ @brief Dumps the signature registers for 3D modules...
+ @param psDevId - device ID info
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_UINT32 ui32DumpFrameNum,
IMG_BOOL bLastFrame,
@@ -1686,6 +2025,17 @@ PVRSRV_ERROR PDump3DSignatureRegisters(PVRSRV_DEVICE_IDENTIFIER *psDevId,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpTASignatureRegisters
+ @brief Dumps the TA signature registers
+ @param psDevId - device id info
+ @param ui32DumpFrameNum - frame number
+ @param ui32TAKickCount - TA kick counter
+ @param bLastFrame
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpTASignatureRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_UINT32 ui32DumpFrameNum,
IMG_UINT32 ui32TAKickCount,
@@ -1718,6 +2068,16 @@ PVRSRV_ERROR PDumpTASignatureRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpCounterRegisters
+ @brief Dumps the performance counters
+ @param psDevId - device id info
+ @param ui32DumpFrameNum - frame number
+ @param bLastFrame
+ @param pui32Registers - register list
+ @param ui32NumRegisters - number of regs to dump
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_UINT32 ui32DumpFrameNum,
IMG_BOOL bLastFrame,
@@ -1750,6 +2110,14 @@ PVRSRV_ERROR PDumpCounterRegisters (PVRSRV_DEVICE_IDENTIFIER *psDevId,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpRegRead
+ @brief Dump signature register read to script
+ @param pszPDumpDevName - pdump device name
+ @param ui32RegOffset - register offset
+ @param ui32Flags - pdump flags
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
const IMG_UINT32 ui32RegOffset,
IMG_UINT32 ui32Flags)
@@ -1768,6 +2136,17 @@ PVRSRV_ERROR PDumpRegRead(IMG_CHAR *pszPDumpRegName,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpSaveMemKM
+ @brief Save device memory to a file
+ @param psDevId
+ @param pszFileName
+ @param ui32FileOffset
+ @param sDevBaseAddr
+ @param ui32Size
+ @param ui32PDumpFlags
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
@@ -1797,6 +2176,13 @@ PVRSRV_ERROR PDumpSaveMemKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
return PVRSRV_OK;
}
+/*****************************************************************************
+ @name PDumpCycleCountRegRead
+ @brief Dump counter register read to script
+ @param ui32RegOffset - register offset
+ @param bLastFrame
+ @return Error
+*****************************************************************************/
PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
const IMG_UINT32 ui32RegOffset,
IMG_BOOL bLastFrame)
@@ -1816,6 +2202,18 @@ PVRSRV_ERROR PDumpCycleCountRegRead(PVRSRV_DEVICE_IDENTIFIER *psDevId,
}
+/*!
+******************************************************************************
+
+ @Function PDumpSignatureBuffer
+
+ @Description
+
+ Dumps a signature registers buffer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_CHAR *pszBufferType,
@@ -1838,6 +2236,18 @@ PVRSRV_ERROR PDumpSignatureBuffer (PVRSRV_DEVICE_IDENTIFIER *psDevId,
}
+/*!
+******************************************************************************
+
+ @Function PDumpHWPerfCBKM
+
+ @Description
+
+ Dumps the HW Perf Circular Buffer
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
@@ -1852,6 +2262,15 @@ PVRSRV_ERROR PDumpHWPerfCBKM (PVRSRV_DEVICE_IDENTIFIER *psDevId,
}
+/*****************************************************************************
+ FUNCTION : PDumpCBP
+
+ PURPOSE : Dump CBP command to script
+
+ PARAMETERS :
+
+ RETURNS : None
+*****************************************************************************/
PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
IMG_UINT32 ui32ROffOffset,
IMG_UINT32 ui32WPosVal,
@@ -1866,41 +2285,42 @@ PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
IMG_DEV_VIRTADDR sDevVAddr;
IMG_DEV_PHYADDR sDevPAddr;
IMG_DEV_VIRTADDR sDevVPageAddr;
-
+ //IMG_CPU_PHYADDR CpuPAddr;
PDUMP_MMU_ATTRIB *psMMUAttrib;
PDUMP_GET_SCRIPT_STRING();
psMMUAttrib = ((BM_BUF*)psROffMemInfo->sMemBlk.hBuffer)->pMapping->pBMHeap->psMMUAttrib;
-
+ /* Check the offset and size don't exceed the bounds of the allocation */
PVR_ASSERT((ui32ROffOffset + sizeof(IMG_UINT32)) <= psROffMemInfo->uAllocSize);
pui8LinAddr = psROffMemInfo->pvLinAddrKM;
sDevVAddr = psROffMemInfo->sDevVAddr;
-
+ /* Advance addresses by offset */
pui8LinAddr += ui32ROffOffset;
sDevVAddr.uiAddr += ui32ROffOffset;
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
PDumpOSCPUVAddrToPhysPages(psROffMemInfo->sMemBlk.hOSMemHandle,
ui32ROffOffset,
pui8LinAddr,
psMMUAttrib->ui32DataPageMask,
&ui32PageOffset);
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = sDevVAddr.uiAddr - ui32PageOffset;
PVR_ASSERT((sDevVPageAddr.uiAddr & 0xFFF) == 0);
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psROffMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageOffset;
eErr = PDumpOSBufprintf(hScript,
@@ -1922,6 +2342,13 @@ PVRSRV_ERROR PDumpCBP(PPVRSRV_KERNEL_MEM_INFO psROffMemInfo,
}
+/**************************************************************************
+ * Function Name : PDumpIDLWithFlags
+ * Inputs : Idle time in clocks
+ * Outputs : None
+ * Returns : Error
+ * Description : Dump IDL command to script
+**************************************************************************/
PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
{
PVRSRV_ERROR eErr;
@@ -1938,11 +2365,31 @@ PVRSRV_ERROR PDumpIDLWithFlags(IMG_UINT32 ui32Clocks, IMG_UINT32 ui32Flags)
}
+/**************************************************************************
+ * Function Name : PDumpIDL
+ * Inputs : Idle time in clocks
+ * Outputs : None
+ * Returns : Error
+ * Description : Dump IDL command to script
+**************************************************************************/
PVRSRV_ERROR PDumpIDL(IMG_UINT32 ui32Clocks)
{
return PDumpIDLWithFlags(ui32Clocks, PDUMP_FLAGS_CONTINUOUS);
}
+/**************************************************************************
+ * Function Name : PDumpMemUM
+ * Inputs : pvAltLinAddrUM
+ * : pvLinAddrUM
+ * : psMemInfo
+ * : ui32Offset
+ * : ui32Bytes
+ * : ui32Flags
+ * : hUniqueTag
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Dump user mode memory
+**************************************************************************/
PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_PVOID pvAltLinAddrUM,
IMG_PVOID pvLinAddrUM,
@@ -1954,12 +2401,14 @@ PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
{
IMG_VOID *pvAddrUM;
IMG_VOID *pvAddrKM;
- IMG_UINT32 ui32BytesDumped;
- IMG_UINT32 ui32CurrentOffset;
+ PVRSRV_ERROR eError;
if (psMemInfo->pvLinAddrKM != IMG_NULL && pvAltLinAddrUM == IMG_NULL)
{
-
+ /*
+ * There is a kernel virtual address for the memory that is
+ * being dumped, and no alternate user mode linear address.
+ */
return PDumpMemKM(IMG_NULL,
psMemInfo,
ui32Offset,
@@ -1972,7 +2421,10 @@ PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
pvAddrKM = GetTempBuffer();
-
+ /*
+ * The memory to be dumped needs to be copied in from
+ * the client. Dump the memory, a buffer at a time.
+ */
PVR_ASSERT(pvAddrUM != IMG_NULL && pvAddrKM != IMG_NULL);
if (pvAddrUM == IMG_NULL || pvAddrKM == IMG_NULL)
{
@@ -1985,59 +2437,131 @@ PVRSRV_ERROR PDumpMemUM(PVRSRV_PER_PROCESS_DATA *psPerProc,
PDumpCommentWithFlags(ui32Flags, "Dumping 0x%08x bytes of memory, in blocks of 0x%08x bytes", ui32Bytes, (IMG_UINT32)PDUMP_TEMP_BUFFER_SIZE);
}
- ui32CurrentOffset = ui32Offset;
- for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
+ if (psMemInfo->ui32Flags & PVRSRV_MEM_SPARSE)
{
- PVRSRV_ERROR eError;
- IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+ /*
+ In case of sparse mappings we can't just copy the full range as not
+ all pages are valid, instead we walk a page at a time only dumping
+ if the a page exists at that address
+ */
+ IMG_UINT32 ui32BytesRemain = ui32Bytes;
+ IMG_UINT32 ui32InPageStart = ui32Offset & (~HOST_PAGEMASK);
+ IMG_UINT32 ui32PageOffset = ui32Offset & (HOST_PAGEMASK);
+ IMG_UINT32 ui32BytesToCopy = MIN(HOST_PAGESIZE() - ui32InPageStart, ui32BytesRemain);
- eError = OSCopyFromUser(psPerProc,
- pvAddrKM,
- pvAddrUM,
- ui32BytesToDump);
- if (eError != PVRSRV_OK)
+ do
{
- PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
- return eError;
- }
+ if (BM_MapPageAtOffset(BM_MappingHandleFromBuffer(psMemInfo->sMemBlk.hBuffer), ui32PageOffset))
+ {
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToCopy);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+ return eError;
+ }
- eError = PDumpMemKM(pvAddrKM,
- psMemInfo,
- ui32CurrentOffset,
- ui32BytesToDump,
- ui32Flags,
- hUniqueTag);
+ /*
+ At this point we know we're dumping a valid page so call
+ the internal function
+ */
+ eError = _PDumpMemIntKM(pvAddrKM,
+ psMemInfo,
+ ui32PageOffset + ui32InPageStart,
+ ui32BytesToCopy,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+ /*
+ * If writing fails part way through, then some
+ * investigation is needed.
+ */
+ if (ui32BytesToCopy != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+ PVR_ASSERT(ui32BytesToCopy == 0);
+ return eError;
+ }
+ }
- if (eError != PVRSRV_OK)
+ VPTR_INC(pvAddrUM, ui32BytesToCopy);
+ ui32BytesRemain -= ui32BytesToCopy;
+ ui32InPageStart = 0;
+ ui32PageOffset += HOST_PAGESIZE();
+ } while(ui32BytesRemain);
+ }
+ else
+ {
+ IMG_UINT32 ui32CurrentOffset = ui32Offset;
+ IMG_UINT32 ui32BytesDumped;
+
+ for (ui32BytesDumped = 0; ui32BytesDumped < ui32Bytes;)
{
-
- if (ui32BytesDumped != 0)
+ IMG_UINT32 ui32BytesToDump = MIN(PDUMP_TEMP_BUFFER_SIZE, ui32Bytes - ui32BytesDumped);
+
+ eError = OSCopyFromUser(psPerProc,
+ pvAddrKM,
+ pvAddrUM,
+ ui32BytesToDump);
+ if (eError != PVRSRV_OK)
{
- PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: OSCopyFromUser failed (%d)", eError));
+ return eError;
}
- PVR_ASSERT(ui32BytesDumped == 0);
- return eError;
+
+ eError = PDumpMemKM(pvAddrKM,
+ psMemInfo,
+ ui32CurrentOffset,
+ ui32BytesToDump,
+ ui32Flags,
+ hUniqueTag);
+
+ if (eError != PVRSRV_OK)
+ {
+ /*
+ * If writing fails part way through, then some
+ * investigation is needed.
+ */
+ if (ui32BytesDumped != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PDumpMemUM: PDumpMemKM failed (%d)", eError));
+ }
+ PVR_ASSERT(ui32BytesDumped == 0);
+ return eError;
+ }
+
+ VPTR_INC(pvAddrUM, ui32BytesToDump);
+ ui32CurrentOffset += ui32BytesToDump;
+ ui32BytesDumped += ui32BytesToDump;
}
-
- VPTR_INC(pvAddrUM, ui32BytesToDump);
- ui32CurrentOffset += ui32BytesToDump;
- ui32BytesDumped += ui32BytesToDump;
}
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : _PdumpAllocMMUContext
+ * Inputs : pui32MMUContextID
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : pdump util to allocate MMU contexts
+**************************************************************************/
static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
{
IMG_UINT32 i;
-
+ /* there are MAX_PDUMP_MMU_CONTEXTS contexts available, find one */
for(i=0; i<MAX_PDUMP_MMU_CONTEXTS; i++)
{
if((gui16MMUContextUsage & (1U << i)) == 0)
{
-
+ /* mark in use */
gui16MMUContextUsage |= 1U << i;
*pui32MMUContextID = i;
return PVRSRV_OK;
@@ -2050,11 +2574,18 @@ static PVRSRV_ERROR _PdumpAllocMMUContext(IMG_UINT32 *pui32MMUContextID)
}
+/**************************************************************************
+ * Function Name : _PdumpFreeMMUContext
+ * Inputs : ui32MMUContextID
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : pdump util to free MMU contexts
+**************************************************************************/
static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
{
if(ui32MMUContextID < MAX_PDUMP_MMU_CONTEXTS)
{
-
+ /* free the id */
gui16MMUContextUsage &= ~(1U << ui32MMUContextID);
return PVRSRV_OK;
}
@@ -2065,6 +2596,13 @@ static PVRSRV_ERROR _PdumpFreeMMUContext(IMG_UINT32 ui32MMUContextID)
}
+/**************************************************************************
+ * Function Name : PDumpSetMMUContext
+ * Inputs :
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Set MMU Context
+**************************************************************************/
PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_CHAR *pszMemSpace,
IMG_UINT32 *pui32MMUContextID,
@@ -2087,11 +2625,11 @@ PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
return eErr;
}
-
-
+ /* derive the DevPAddr */
+ /* FIXME: if we used OSMemHandleToCPUPAddr() here, we could lose the lin addr arg */
sCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle, pui8LinAddr);
sDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
-
+ /* and round to 4k page */
sDevPAddr.uiAddr &= ~((PVRSRV_4K_PAGE_SIZE) -1);
eErr = PDumpOSBufprintf(hScript,
@@ -2109,13 +2647,20 @@ PVRSRV_ERROR PDumpSetMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
}
PDumpOSWriteString2(hScript, PDUMP_FLAGS_CONTINUOUS);
-
+ /* return the MMU Context ID */
*pui32MMUContextID = ui32MMUContextID;
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpClearMMUContext
+ * Inputs :
+ * Outputs : None
+ * Returns : PVRSRV_ERROR
+ * Description : Clear MMU Context
+**************************************************************************/
PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_CHAR *pszMemSpace,
IMG_UINT32 ui32MMUContextID,
@@ -2126,7 +2671,9 @@ PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
PVR_UNREFERENCED_PARAMETER(eDeviceType);
PVR_UNREFERENCED_PARAMETER(ui32MMUType);
-
+ /* FIXME: Propagate error from PDumpComment once it's supported on
+ * all OSes and platforms
+ */
PDumpComment("Clear MMU Context for memory space %s\r\n", pszMemSpace);
eErr = PDumpOSBufprintf(hScript,
ui32MaxLen,
@@ -2149,6 +2696,15 @@ PVRSRV_ERROR PDumpClearMMUContext(PVRSRV_DEVICE_TYPE eDeviceType,
return PVRSRV_OK;
}
+/*****************************************************************************
+ FUNCTION : PDumpStoreMemToFile
+
+ PURPOSE : Dumps a given addr:size to a file
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
@@ -2164,18 +2720,19 @@ PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
PDUMP_GET_SCRIPT_STRING();
-
-
-
+ /*
+ query the buffer manager for the physical pages that back the
+ virtual address
+ */
ui32PageOffset = (IMG_UINT32)((IMG_UINTPTR_T)psMemInfo->pvLinAddrKM & psMMUAttrib->ui32DataPageMask);
-
+ /* calculate the DevV page address */
sDevVPageAddr.uiAddr = uiAddr - ui32PageOffset;
-
+ /* get the physical page address based on the device virtual address */
BM_GetPhysPageAddr(psMemInfo, sDevVPageAddr, &sDevPAddr);
-
+ /* convert DevP page address to byte address */
sDevPAddr.uiAddr += ui32PageOffset;
PDumpOSBufprintf(hScript,
@@ -2194,6 +2751,15 @@ PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
return PVRSRV_OK;
}
+/*****************************************************************************
+ FUNCTION : PDumpRegBasedCBP
+
+ PURPOSE : Dump CBP command to script
+
+ PARAMETERS :
+
+ RETURNS : None
+*****************************************************************************/
PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
IMG_UINT32 ui32RegOffset,
IMG_UINT32 ui32WPosVal,
@@ -2217,16 +2783,26 @@ PVRSRV_ERROR PDumpRegBasedCBP(IMG_CHAR *pszPDumpRegName,
}
-
+/****************************************************
+ * Non-uitron code here.
+ * For example, code communicating with dbg driver.
+ ***************************************************/
+/* PRQA S 5087 1 */ /* include file needed here */
#include "syscommon.h"
+/**************************************************************************
+ * Function Name : PDumpConnectionNotify
+ * Description : Called by the debugdrv to tell Services that pdump has
+ * connected
+ * NOTE: No debugdrv on uitron.
+ **************************************************************************/
IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
{
SYS_DATA *psSysData;
PVRSRV_DEVICE_NODE *psThis;
PVR_DPF((PVR_DBG_WARNING, "PDump has connected."));
-
+ /* Loop over all known devices */
SysAcquireData(&psSysData);
psThis = psSysData->psDeviceNodeList;
@@ -2234,27 +2810,39 @@ IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID)
{
if (psThis->pfnPDumpInitDevice)
{
-
+ /* Reset pdump according to connected device */
psThis->pfnPDumpInitDevice(psThis);
}
psThis = psThis->psNext;
}
}
+/*****************************************************************************
+ * Function Name : DbgWrite
+ * Inputs : psStream - debug stream to write to
+ pui8Data - buffer
+ ui32BCount - buffer length
+ ui32Flags - flags, e.g. continuous, LF
+ * Outputs : None
+ * Returns : Bytes written
+ * Description : Write a block of data to a debug stream
+ * NOTE: No debugdrv on uitron.
+ *****************************************************************************/
IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BCount, IMG_UINT32 ui32Flags)
{
IMG_UINT32 ui32BytesWritten = 0;
IMG_UINT32 ui32Off = 0;
PDBG_STREAM_CONTROL psCtrl = psStream->psCtrl;
-
+ /* Return immediately if marked as "never" */
if ((ui32Flags & PDUMP_FLAGS_NEVER) != 0)
{
return ui32BCount;
}
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Return if process is not marked for pdumping, unless it's persistent.
+ */
if ( (_PDumpIsProcessActive() == IMG_FALSE ) &&
((ui32Flags & PDUMP_FLAGS_PERSISTENT) == 0) )
{
@@ -2262,14 +2850,18 @@ IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BC
}
#endif
-
+ /* Send persistent data first ...
+ * If we're still initialising the params will be captured to the
+ * init stream in the call to pfnDBGDrivWrite2 below.
+ */
if ( ((ui32Flags & PDUMP_FLAGS_PERSISTENT) != 0) && (psCtrl->bInitPhaseComplete) )
{
while (ui32BCount > 0)
{
-
-
-
+ /*
+ Params marked as persistent should be appended to the init phase.
+ For example window system mem mapping of the primary surface.
+ */
ui32BytesWritten = PDumpOSDebugDriverWrite( psStream,
PDUMP_WRITE_MODE_PERSISTENT,
&pui8Data[ui32Off], ui32BCount, 1, 0);
@@ -2289,14 +2881,14 @@ IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BC
PVR_DPF((PVR_DBG_ERROR, "DbgWrite: Failed to send persistent data"));
if( (psCtrl->ui32Flags & DEBUG_FLAGS_READONLY) != 0)
{
-
+ /* suspend pdump to prevent flooding kernel log buffer */
PDumpSuspendKM();
}
return 0xFFFFFFFFU;
}
}
-
+ /* reset buffer counters */
ui32BCount = ui32Off; ui32Off = 0; ui32BytesWritten = 0;
}
@@ -2304,8 +2896,9 @@ IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BC
{
if ((ui32Flags & PDUMP_FLAGS_CONTINUOUS) != 0)
{
-
-
+ /*
+ If pdump client (or its equivalent) isn't running then throw continuous data away.
+ */
if (((psCtrl->ui32CapMode & DEBUG_CAPMODE_FRAMED) != 0) &&
(psCtrl->ui32Start == 0xFFFFFFFFU) &&
(psCtrl->ui32End == 0xFFFFFFFFU) &&
@@ -2344,9 +2937,10 @@ IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BC
}
}
-
-
-
+ /*
+ If the debug driver's buffers are full so no data could be written then yield
+ execution so pdump can run and empty them.
+ */
if (ui32BytesWritten == 0)
{
PDumpOSReleaseExecution();
@@ -2358,15 +2952,17 @@ IMG_UINT32 DbgWrite(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32BC
ui32BCount -= ui32BytesWritten;
}
-
+ /* loop exits when i) all data is written, or ii) an unrecoverable error occurs */
}
-
-
return ui32BytesWritten;
}
-#else
-#endif
+#else /* defined(PDUMP) */
+/* disable warning about empty module */
+#endif /* defined(PDUMP) */
+/*****************************************************************************
+ End of file (pdump_common.c)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/common/perproc.c b/sgx/services4/srvkm/common/perproc.c
index eb73166..f228828 100644
--- a/sgx/services4/srvkm/common/perproc.c
+++ b/sgx/services4/srvkm/common/perproc.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Per-process storage
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manage per-process storage
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "resman.h"
@@ -37,6 +54,18 @@
static HASH_TABLE *psHashTab = IMG_NULL;
+/*!
+******************************************************************************
+
+ @Function FreePerProcData
+
+ @Description Free a per-process data area
+
+ @Input psPerProc - pointer to per-process data area
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
{
PVRSRV_ERROR eError;
@@ -54,7 +83,10 @@ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
if (uiPerProc == 0)
{
PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't find process in per-process data hash table"));
-
+ /*
+ * We must have failed early in the per-process data area
+ * creation, before the process ID was set.
+ */
PVR_ASSERT(psPerProc->ui32PID == 0);
}
else
@@ -63,7 +95,7 @@ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
PVR_ASSERT(((PVRSRV_PER_PROCESS_DATA *)uiPerProc)->ui32PID == psPerProc->ui32PID);
}
-
+ /* Free handle base for this process */
if (psPerProc->psHandleBase != IMG_NULL)
{
eError = PVRSRVFreeHandleBase(psPerProc->psHandleBase);
@@ -74,7 +106,7 @@ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
}
}
-
+ /* Release handle for per-process data area */
if (psPerProc->hPerProcData != IMG_NULL)
{
eError = PVRSRVReleaseHandle(KERNEL_HANDLE_BASE, psPerProc->hPerProcData, PVRSRV_HANDLE_TYPE_PERPROC_DATA);
@@ -86,7 +118,7 @@ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
}
}
-
+ /* Call environment specific per process deinit function */
eError = OSPerProcessPrivateDataDeInit(psPerProc->hOsPrivateData);
if (eError != PVRSRV_OK)
{
@@ -98,7 +130,7 @@ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
sizeof(*psPerProc),
psPerProc,
psPerProc->hBlockAlloc);
-
+ /*not nulling pointer, copy on stack*/
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "FreePerProcessData: Couldn't free per-process data (%d)", eError));
@@ -109,18 +141,44 @@ static PVRSRV_ERROR FreePerProcessData(PVRSRV_PER_PROCESS_DATA *psPerProc)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessData
+
+ @Description Return per-process data area
+
+ @Input ui32PID - process ID
+
+ @Return Pointer to per-process data area, or IMG_NULL on error.
+
+******************************************************************************/
PVRSRV_PER_PROCESS_DATA *PVRSRVPerProcessData(IMG_UINT32 ui32PID)
{
PVRSRV_PER_PROCESS_DATA *psPerProc;
PVR_ASSERT(psHashTab != IMG_NULL);
-
+ /* Look for existing per-process data area */
psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
return psPerProc;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataConnect
+
+ @Description Allocate per-process data area, or increment refcount if one
+ already exists for this PID.
+
+ @Input ui32PID - process ID
+ ppsPerProc - Pointer to per-process data area
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
{
PVRSRV_PER_PROCESS_DATA *psPerProc;
@@ -132,12 +190,12 @@ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flag
return PVRSRV_ERROR_INIT_FAILURE;
}
-
+ /* Look for existing per-process data area */
psPerProc = (PVRSRV_PER_PROCESS_DATA *)HASH_Retrieve(psHashTab, (IMG_UINTPTR_T)ui32PID);
if (psPerProc == IMG_NULL)
{
-
+ /* Allocate per-process data area */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(*psPerProc),
(IMG_PVOID *)&psPerProc,
@@ -170,7 +228,7 @@ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flag
PVR_UNREFERENCED_PARAMETER(ui32Flags);
#endif
-
+ /* Call environment specific per process init function */
eError = OSPerProcessPrivateDataInit(&psPerProc->hOsPrivateData);
if (eError != PVRSRV_OK)
{
@@ -178,7 +236,7 @@ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flag
goto failure;
}
-
+ /* Allocate a handle for the per-process data area */
eError = PVRSRVAllocHandle(KERNEL_HANDLE_BASE,
&psPerProc->hPerProcData,
psPerProc,
@@ -190,7 +248,7 @@ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flag
goto failure;
}
-
+ /* Allocate handle base for this process */
eError = PVRSRVAllocHandleBase(&psPerProc->psHandleBase);
if (eError != PVRSRV_OK)
{
@@ -198,7 +256,7 @@ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flag
goto failure;
}
-
+ /* Set per-process handle options */
eError = OSPerProcessSetHandleOptions(psPerProc->psHandleBase);
if (eError != PVRSRV_OK)
{
@@ -206,7 +264,7 @@ PVRSRV_ERROR PVRSRVPerProcessDataConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flag
goto failure;
}
-
+ /* Create a resource manager context for the process */
eError = PVRSRVResManConnect(psPerProc, &psPerProc->hResManContext);
if (eError != PVRSRV_OK)
{
@@ -231,6 +289,19 @@ failure:
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataDisconnect
+
+ @Description Decrement refcount for per-process data area,
+ and free the resources if necessary.
+
+ @Input ui32PID - process ID
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
{
PVRSRV_ERROR eError;
@@ -255,10 +326,10 @@ IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
PVRSRVTimeTraceBufferDestroy(ui32PID);
#endif
-
+ /* Close the Resource Manager connection */
PVRSRVResManDisconnect(psPerProc->hResManContext, IMG_FALSE);
-
+ /* Free the per-process data */
eError = FreePerProcessData(psPerProc);
if (eError != PVRSRV_OK)
{
@@ -275,11 +346,21 @@ IMG_VOID PVRSRVPerProcessDataDisconnect(IMG_UINT32 ui32PID)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataInit
+
+ @Description Initialise per-process data management
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
{
PVR_ASSERT(psHashTab == IMG_NULL);
-
+ /* Create hash table */
psHashTab = HASH_Create(HASH_TAB_INIT_SIZE);
if (psHashTab == IMG_NULL)
{
@@ -290,12 +371,22 @@ PVRSRV_ERROR PVRSRVPerProcessDataInit(IMG_VOID)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPerProcessDataDeInit
+
+ @Description De-initialise per-process data management
+
+ @Return Error code, or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
{
-
+ /* Destroy per-process data area hash table */
if (psHashTab != IMG_NULL)
{
-
+ /* Free the hash table */
HASH_Delete(psHashTab);
psHashTab = IMG_NULL;
}
@@ -303,3 +394,6 @@ PVRSRV_ERROR PVRSRVPerProcessDataDeInit(IMG_VOID)
return PVRSRV_OK;
}
+/******************************************************************************
+ End of file (perproc.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/power.c b/sgx/services4/srvkm/common/power.c
index 21d7ad4..93661ed 100644
--- a/sgx/services4/srvkm/common/power.c
+++ b/sgx/services4/srvkm/common/power.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Power management functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for power management functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "pdump_km.h"
@@ -33,6 +50,19 @@ static IMG_BOOL gbInitServerRunning = IMG_FALSE;
static IMG_BOOL gbInitServerRan = IMG_FALSE;
static IMG_BOOL gbInitSuccessful = IMG_FALSE;
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetInitServerState
+
+ @Description Sets given services init state.
+
+ @Input eInitServerState : a services init state
+ @Input bState : a state to set
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState, IMG_BOOL bState)
{
@@ -57,6 +87,18 @@ PVRSRV_ERROR PVRSRVSetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetInitServerState
+
+ @Description Tests whether a given services init state was run.
+
+ @Input eInitServerState : a services init state
+
+ @Return IMG_BOOL
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
{
@@ -82,12 +124,38 @@ IMG_BOOL PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_STATE eInitServerState)
return bReturnVal;
}
+/*!
+******************************************************************************
+
+ @Function _IsSystemStatePowered
+
+ @Description Tests whether a given system state represents powered-up.
+
+ @Input eSystemPowerState : a system power state
+
+ @Return IMG_BOOL
+
+******************************************************************************/
static IMG_BOOL _IsSystemStatePowered(PVRSRV_SYS_POWER_STATE eSystemPowerState)
{
return (IMG_BOOL)(eSystemPowerState < PVRSRV_SYS_POWER_STATE_D2);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPowerLock
+
+ @Description Obtain the mutex for power transitions
+
+ @Input ui32CallerID : KERNEL_ID or ISR_ID
+ @Input bSystemPowerEvent : Only pass IMG_TRUE if the lock is for a
+ system power state change
+
+ @Return PVRSRV_ERROR IMG_CALLCONV
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
IMG_BOOL bSystemPowerEvent)
@@ -115,8 +183,9 @@ PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
}
else if (bTryLock)
{
-
-
+ /*
+ ISR failed to acquire lock so it must be held by a kernel thread.
+ */
eError = PVRSRV_ERROR_RETRY;
break;
}
@@ -130,12 +199,12 @@ PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
OSPowerLockUnwrap();
}
-
+ /* PRQA S 3415 3 */ /* side effects desired */
if ((eError == PVRSRV_OK) &&
!bSystemPowerEvent &&
!_IsSystemStatePowered(psSysData->eCurrentPowerState))
{
-
+ /* Reject device power state change due to system power state. */
PVRSRVPowerUnlock(ui32CallerID);
eError = PVRSRV_ERROR_RETRY;
}
@@ -144,6 +213,18 @@ PVRSRV_ERROR PVRSRVPowerLock(IMG_UINT32 ui32CallerID,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVPowerUnlock
+
+ @Description Release the mutex for power transitions
+
+ @Input ui32CallerID : KERNEL_ID or ISR_ID
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
{
@@ -152,17 +233,36 @@ IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePrePowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input psPowerDevice : the device
+ @Input va : variable argument list with:
+ bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ ui32DeviceIndex : device index
+ eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
{
PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
PVRSRV_ERROR eError;
-
+ /*Variable Argument variables*/
IMG_BOOL bAllDevices;
IMG_UINT32 ui32DeviceIndex;
PVRSRV_DEV_POWER_STATE eNewPowerState;
-
+ /* WARNING: if types were not aligned to 4 bytes, this could be dangerous. */
bAllDevices = va_arg(va, IMG_BOOL);
ui32DeviceIndex = va_arg(va, IMG_UINT32);
eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
@@ -176,7 +276,7 @@ static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowe
{
if (psPowerDevice->pfnPrePower != IMG_NULL)
{
-
+ /* Call the device's power callback. */
eError = psPowerDevice->pfnPrePower(psPowerDevice->hDevCookie,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
@@ -186,7 +286,7 @@ static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowe
}
}
-
+ /* Do any required system-layer processing. */
eError = SysDevicePrePowerState(psPowerDevice->ui32DeviceIndex,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
@@ -200,6 +300,23 @@ static PVRSRV_ERROR PVRSRVDevicePrePowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowe
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePrePowerStateKM
+
+ @Description
+
+ Perform device-specific processing required before a power transition
+
+ @Input bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
IMG_UINT32 ui32DeviceIndex,
@@ -210,7 +327,7 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
SysAcquireData(&psSysData);
-
+ /* Loop through the power devices. */
eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
&PVRSRVDevicePrePowerStateKM_AnyVaCb,
bAllDevices,
@@ -220,17 +337,36 @@ PVRSRV_ERROR PVRSRVDevicePrePowerStateKM(IMG_BOOL bAllDevices,
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostPowerStateKM_AnyVaCb
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input psPowerDevice : the device
+ @Input va : variable argument list with:
+ bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ ui32DeviceIndex : device index
+ eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPowerDevice, va_list va)
{
PVRSRV_DEV_POWER_STATE eNewDevicePowerState;
PVRSRV_ERROR eError;
-
+ /*Variable Argument variables*/
IMG_BOOL bAllDevices;
IMG_UINT32 ui32DeviceIndex;
PVRSRV_DEV_POWER_STATE eNewPowerState;
-
+ /* WARNING: if types were not aligned to 4 bytes, this could be dangerous. */
bAllDevices = va_arg(va, IMG_BOOL);
ui32DeviceIndex = va_arg(va, IMG_UINT32);
eNewPowerState = va_arg(va, PVRSRV_DEV_POWER_STATE);
@@ -242,7 +378,7 @@ static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPow
if (psPowerDevice->eCurrentPowerState != eNewDevicePowerState)
{
-
+ /* Do any required system-layer processing. */
eError = SysDevicePostPowerState(psPowerDevice->ui32DeviceIndex,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
@@ -253,7 +389,7 @@ static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPow
if (psPowerDevice->pfnPostPower != IMG_NULL)
{
-
+ /* Call the device's power callback. */
eError = psPowerDevice->pfnPostPower(psPowerDevice->hDevCookie,
eNewDevicePowerState,
psPowerDevice->eCurrentPowerState);
@@ -269,6 +405,23 @@ static PVRSRV_ERROR PVRSRVDevicePostPowerStateKM_AnyVaCb(PVRSRV_POWER_DEV *psPow
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostPowerStateKM
+
+ @Description
+
+ Perform device-specific processing required after a power transition
+
+ @Input bAllDevices : IMG_TRUE - All devices
+ IMG_FALSE - Use ui32DeviceIndex
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
IMG_UINT32 ui32DeviceIndex,
@@ -279,7 +432,7 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
SysAcquireData(&psSysData);
-
+ /* Loop through the power devices. */
eError = List_PVRSRV_POWER_DEV_PVRSRV_ERROR_Any_va(psSysData->psPowerDeviceList,
&PVRSRVDevicePostPowerStateKM_AnyVaCb,
bAllDevices,
@@ -290,30 +443,38 @@ PVRSRV_ERROR PVRSRVDevicePostPowerStateKM(IMG_BOOL bAllDevices,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetDevicePowerStateKM
+
+ @Description Set the Device into a new state
+
+ @Input ui32DeviceIndex : device index
+ @Input eNewPowerState : New power state
+ @Input ui32CallerID : KERNEL_ID or ISR_ID
+ @Input bRetainMutex : If true, the power mutex is retained on exit
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE eNewPowerState,
- IMG_UINT32 ui32CallerID,
- IMG_BOOL bRetainMutex)
+ PVRSRV_DEV_POWER_STATE eNewPowerState)
{
PVRSRV_ERROR eError;
SYS_DATA *psSysData;
SysAcquireData(&psSysData);
- eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
- if(eError != PVRSRV_OK)
- {
- return eError;
- }
-
#if defined(PDUMP)
if (eNewPowerState == PVRSRV_DEV_POWER_STATE_DEFAULT)
{
-
-
-
-
+ /*
+ Pdump a power-up regardless of the default state.
+ Then disable pdump and transition to the default power state.
+ This ensures that a power-up is always present in the pdump when necessary.
+ */
eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, PVRSRV_DEV_POWER_STATE_ON);
if(eError != PVRSRV_OK)
{
@@ -329,7 +490,7 @@ PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
PDUMPSUSPEND();
}
- #endif
+ #endif /* PDUMP */
eError = PVRSRVDevicePrePowerStateKM(IMG_FALSE, ui32DeviceIndex, eNewPowerState);
if(eError != PVRSRV_OK)
@@ -356,15 +517,22 @@ Exit:
"PVRSRVSetDevicePowerStateKM : Transition to %d FAILED 0x%x", eNewPowerState, eError));
}
- if (!bRetainMutex || (eError != PVRSRV_OK))
- {
- PVRSRVPowerUnlock(ui32CallerID);
- }
-
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemPrePowerStateKM
+
+ @Description Perform processing required before a system power transition
+
+ @Input eNewSysPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
{
@@ -374,7 +542,7 @@ PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerStat
SysAcquireData(&psSysData);
-
+ /* This mutex is unlocked in PVRSRVSystemPostPowerStateKM() */
eError = PVRSRVPowerLock(KERNEL_ID, IMG_TRUE);
if(eError != PVRSRV_OK)
{
@@ -386,7 +554,7 @@ PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerStat
{
if (_IsSystemStatePowered(eNewSysPowerState))
{
-
+ /* Return device back to its default state. */
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
}
else
@@ -394,7 +562,7 @@ PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerStat
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
}
-
+ /* Perform device-specific transitions. */
eError = PVRSRVDevicePrePowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
if (eError != PVRSRV_OK)
{
@@ -404,7 +572,7 @@ PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerStat
if (eNewSysPowerState != psSysData->eCurrentPowerState)
{
-
+ /* Perform system-specific power transitions. */
eError = SysSystemPrePowerState(eNewSysPowerState);
if (eError != PVRSRV_OK)
{
@@ -420,7 +588,7 @@ ErrorExit:
"PVRSRVSystemPrePowerStateKM: Transition from %d to %d FAILED 0x%x",
psSysData->eCurrentPowerState, eNewSysPowerState, eError));
-
+ /* save the power state for the re-attempt */
psSysData->eFailedPowerState = eNewSysPowerState;
PVRSRVPowerUnlock(KERNEL_ID);
@@ -429,6 +597,18 @@ ErrorExit:
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemPostPowerStateKM
+
+ @Description Perform processing required after a system power transition
+
+ @Input eNewSysPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
{
@@ -440,7 +620,7 @@ PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerSta
if (eNewSysPowerState != psSysData->eCurrentPowerState)
{
-
+ /* Perform system-specific power transitions. */
eError = SysSystemPostPowerState(eNewSysPowerState);
if (eError != PVRSRV_OK)
{
@@ -453,7 +633,7 @@ PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerSta
{
if (_IsSystemStatePowered(eNewSysPowerState))
{
-
+ /* Return device back to its default state. */
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_DEFAULT;
}
else
@@ -461,7 +641,7 @@ PVRSRV_ERROR PVRSRVSystemPostPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerSta
eNewDevicePowerState = PVRSRV_DEV_POWER_STATE_OFF;
}
-
+ /* Perform device-specific power transitions. */
eError = PVRSRVDevicePostPowerStateKM(IMG_TRUE, 0, eNewDevicePowerState);
if (eError != PVRSRV_OK)
{
@@ -479,13 +659,14 @@ Exit:
PVRSRVPowerUnlock(KERNEL_ID);
-
+ /* PRQA S 3415 2 */ /* side effects desired */
if (_IsSystemStatePowered(eNewSysPowerState) &&
PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL))
{
-
-
-
+ /*
+ Reprocess the devices' queues in case commands were blocked during
+ the power transition.
+ */
PVRSRVScheduleDeviceCallbacks();
}
@@ -493,6 +674,18 @@ Exit:
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSetPowerStateKM
+
+ @Description Set the system into a new state
+
+ @Input eNewPowerState :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
{
@@ -513,7 +706,7 @@ PVRSRV_ERROR PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE eNewSysPowerState)
goto ErrorExit;
}
-
+ /* save new power state */
psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
return PVRSRV_OK;
@@ -524,13 +717,35 @@ ErrorExit:
"PVRSRVSetPowerStateKM: Transition from %d to %d FAILED 0x%x",
psSysData->eCurrentPowerState, eNewSysPowerState, eError));
-
+ /* save the power state for the re-attempt */
psSysData->eFailedPowerState = eNewSysPowerState;
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterPowerDevice
+
+ @Description
+
+ Registers a device with the power manager. Passes Pre/Post Power handlers
+ and private device handle to be passed to power handlers
+
+ @Input ui32DeviceIndex : device index
+ @Input pfnPrePower : Pre power transition handler
+ @Input pfnPostPower : Post power transition handler
+ @Input pfnPreClockSpeedChange : Pre clock speed transition handler (if required)
+ @Input pfnPostClockSpeedChange : Post clock speed transition handler (if required)
+ @Input hDevCookie : Dev cookie for dev power handlers
+ @Input eCurrentPowerState : Current power state of the device
+ @Input eDefaultPowerState : Default power state of the device
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
PFN_PRE_POWER pfnPrePower,
PFN_POST_POWER pfnPostPower,
@@ -562,7 +777,7 @@ PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
return eError;
}
-
+ /* setup device for power manager */
psPowerDevice->pfnPrePower = pfnPrePower;
psPowerDevice->pfnPostPower = pfnPostPower;
psPowerDevice->pfnPreClockSpeedChange = pfnPreClockSpeedChange;
@@ -572,13 +787,27 @@ PVRSRV_ERROR PVRSRVRegisterPowerDevice(IMG_UINT32 ui32DeviceIndex,
psPowerDevice->eCurrentPowerState = eCurrentPowerState;
psPowerDevice->eDefaultPowerState = eDefaultPowerState;
-
+ /* insert into power device list */
List_PVRSRV_POWER_DEV_Insert(&(psSysData->psPowerDeviceList), psPowerDevice);
return (PVRSRV_OK);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemovePowerDevice
+
+ @Description
+
+ Removes device from power management register. Device is located by Device Index
+
+ @Input ui32DeviceIndex : device index
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
{
SYS_DATA *psSysData;
@@ -586,7 +815,7 @@ PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
SysAcquireData(&psSysData);
-
+ /* find device in list and remove it */
psPowerDev = (PVRSRV_POWER_DEV*)
List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
&MatchPowerDeviceIndex_AnyVaCb,
@@ -596,13 +825,27 @@ PVRSRV_ERROR PVRSRVRemovePowerDevice (IMG_UINT32 ui32DeviceIndex)
{
List_PVRSRV_POWER_DEV_Remove(psPowerDev);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_POWER_DEV), psPowerDev, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
return (PVRSRV_OK);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVIsDevicePowered
+
+ @Description
+
+ Whether the device is powered, for the purposes of lockup detection.
+
+ @Input ui32DeviceIndex : device index
+
+ @Return IMG_BOOL
+
+******************************************************************************/
IMG_EXPORT
IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
{
@@ -611,7 +854,7 @@ IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
SysAcquireData(&psSysData);
-
+ /* PRQA S 3415 2 */ /* order not important */
if (OSIsResourceLocked(&psSysData->sPowerStateChangeResource, KERNEL_ID) ||
OSIsResourceLocked(&psSysData->sPowerStateChangeResource, ISR_ID))
{
@@ -627,6 +870,22 @@ IMG_BOOL PVRSRVIsDevicePowered(IMG_UINT32 ui32DeviceIndex)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePreClockSpeedChange
+
+ @Description
+
+ Notification from system layer that a device clock speed change is about to happen.
+
+ @Input ui32DeviceIndex : device index
+ @Input bIdleDevice : whether the device should be idled
+ @Input pvInfo
+
+ @Return IMG_VOID
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
IMG_BOOL bIdleDevice,
IMG_VOID *pvInfo)
@@ -641,7 +900,7 @@ PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
if (bIdleDevice)
{
-
+ /* This mutex is released in PVRSRVDevicePostClockSpeedChange. */
eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
if (eError != PVRSRV_OK)
{
@@ -650,7 +909,7 @@ PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
}
}
-
+ /*search the device and then do the pre clock speed change*/
psPowerDevice = (PVRSRV_POWER_DEV*)
List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
&MatchPowerDeviceIndex_AnyVaCb,
@@ -678,6 +937,22 @@ PVRSRV_ERROR PVRSRVDevicePreClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDevicePostClockSpeedChange
+
+ @Description
+
+ Notification from system layer that a device clock speed change has just happened.
+
+ @Input ui32DeviceIndex : device index
+ @Input bIdleDevice : whether the device had been idled
+ @Input pvInfo
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
IMG_BOOL bIdleDevice,
IMG_VOID *pvInfo)
@@ -690,7 +965,7 @@ IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
SysAcquireData(&psSysData);
-
+ /*search the device and then do the post clock speed change*/
psPowerDevice = (PVRSRV_POWER_DEV*)
List_PVRSRV_POWER_DEV_Any_va(psSysData->psPowerDeviceList,
&MatchPowerDeviceIndex_AnyVaCb,
@@ -712,8 +987,11 @@ IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
if (bIdleDevice)
{
-
+ /* This mutex was acquired in PVRSRVDevicePreClockSpeedChange. */
PVRSRVPowerUnlock(KERNEL_ID);
}
}
+/******************************************************************************
+ End of file (power.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/pvrsrv.c b/sgx/services4/srvkm/common/pvrsrv.c
index c0c2349..b9c3253 100644
--- a/sgx/services4/srvkm/common/pvrsrv.c
+++ b/sgx/services4/srvkm/common/pvrsrv.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title core services functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for core services functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/slab.h>
#include "services_headers.h"
@@ -36,6 +53,7 @@
#if defined(TTRACE)
#include "ttrace.h"
#endif
+#include "perfkm.h"
#include "pvrversion.h"
@@ -47,9 +65,26 @@
IMG_UINT32 g_ui32InitFlags;
+/* mark which parts of Services were initialised */
#define INIT_DATA_ENABLE_PDUMPINIT 0x1U
#define INIT_DATA_ENABLE_TTARCE 0x2U
+/*!
+******************************************************************************
+
+ @Function AllocateDeviceID
+
+ @Description
+
+ allocates a device id from the pool of valid ids
+
+ @input psSysData : system data
+
+ @input pui32DevID : device id to return
+
+ @Return device id
+
+******************************************************************************/
PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
{
SYS_DEVICE_ID* psDeviceWalker;
@@ -58,7 +93,7 @@ PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
psDeviceWalker = &psSysData->sDeviceID[0];
psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
-
+ /* find a free ID */
while (psDeviceWalker < psDeviceEnd)
{
if (!psDeviceWalker->bInUse)
@@ -72,13 +107,29 @@ PVRSRV_ERROR AllocateDeviceID(SYS_DATA *psSysData, IMG_UINT32 *pui32DevID)
PVR_DPF((PVR_DBG_ERROR,"AllocateDeviceID: No free and valid device IDs available!"));
-
+ /* Should never get here: sDeviceID[] may have been setup too small */
PVR_ASSERT(psDeviceWalker < psDeviceEnd);
return PVRSRV_ERROR_NO_FREE_DEVICEIDS_AVALIABLE;
}
+/*!
+******************************************************************************
+
+ @Function FreeDeviceID
+
+ @Description
+
+ frees a device id from the pool of valid ids
+
+ @input psSysData : system data
+
+ @input ui32DevID : device id to free
+
+ @Return device id
+
+******************************************************************************/
PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
{
SYS_DEVICE_ID* psDeviceWalker;
@@ -87,10 +138,10 @@ PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
psDeviceWalker = &psSysData->sDeviceID[0];
psDeviceEnd = psDeviceWalker + psSysData->ui32NumDevices;
-
+ /* find the ID to free */
while (psDeviceWalker < psDeviceEnd)
{
-
+ /* if matching id and in use, free */
if (
(psDeviceWalker->uiID == ui32DevID) &&
(psDeviceWalker->bInUse)
@@ -104,13 +155,29 @@ PVRSRV_ERROR FreeDeviceID(SYS_DATA *psSysData, IMG_UINT32 ui32DevID)
PVR_DPF((PVR_DBG_ERROR,"FreeDeviceID: no matching dev ID that is in use!"));
-
+ /* should never get here */
PVR_ASSERT(psDeviceWalker < psDeviceEnd);
return PVRSRV_ERROR_INVALID_DEVICEID;
}
+/*!
+******************************************************************************
+
+ @Function ReadHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset : byte offset from register base
+
+ @Return register value
+
+******************************************************************************/
#ifndef ReadHWReg
IMG_EXPORT
IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
@@ -120,6 +187,24 @@ IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
#endif
+/*!
+******************************************************************************
+
+ @Function WriteHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset : byte offset from register base
+
+ @input ui32Value : value to write to register
+
+ @Return register value : original reg. value
+
+******************************************************************************/
#ifndef WriteHWReg
IMG_EXPORT
IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value)
@@ -132,6 +217,24 @@ IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT3
#endif
+/*!
+******************************************************************************
+
+ @Function WriteHWRegs
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Count : register count
+
+ @input psHWRegs : address/value register list
+
+ @Return none
+
+******************************************************************************/
#ifndef WriteHWRegs
IMG_EXPORT
IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs)
@@ -145,6 +248,19 @@ IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HW
}
#endif
+/*!
+******************************************************************************
+ @Function PVRSRVEnumerateDCKM_ForEachVaCb
+
+ @Description
+
+ Enumerates the device node (if is of the same class as given).
+
+ @Input psDeviceNode - The device node to be enumerated
+ va - variable arguments list, with:
+ pui32DevCount - The device count pointer (to be increased)
+ ppui32DevID - The pointer to the device IDs pointer (to be updated and increased)
+******************************************************************************/
static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
IMG_UINT *pui32DevCount;
@@ -163,11 +279,43 @@ static IMG_VOID PVRSRVEnumerateDevicesKM_ForEachVaCb(PVRSRV_DEVICE_NODE *psDevic
+/*!
+******************************************************************************
+
+ @Function PVRSRVEnumerateDevicesKM
+
+ @Description
+ This function will enumerate all the devices supported by the
+ PowerVR services within the target system.
+ The function returns a list of the device ID strcutres stored either in
+ the services or constructed in the user mode glue component in certain
+ environments. The number of devices in the list is also returned.
+
+ In a binary layered component which does not support dynamic runtime selection,
+ the glue code should compile to return the supported devices statically,
+ e.g. multiple instances of the same device if multiple devices are supported,
+ or the target combination of MBX and display device.
+
+ In the case of an environment (for instance) where one MBX1 may connect to two
+ display devices this code would enumerate all three devices and even
+ non-dynamic MBX1 selection code should retain the facility to parse the list
+ to find the index of the MBX device
+
+ @output pui32NumDevices : On success, contains the number of devices present
+ in the system
+
+ @output psDevIdList : Pointer to called supplied buffer to receive the
+ list of PVRSRV_DEVICE_IDENTIFIER
+
+ @return PVRSRV_ERROR : PVRSRV_NO_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
PVRSRV_DEVICE_IDENTIFIER *psDevIdList)
{
SYS_DATA *psSysData;
+/* PVRSRV_DEVICE_NODE *psDeviceNode; */
IMG_UINT32 i;
if (!pui32NumDevices || !psDevIdList)
@@ -178,20 +326,22 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
SysAcquireData(&psSysData);
-
-
+ /*
+ setup input buffer to be `empty'
+ */
for (i=0; i<PVRSRV_MAX_DEVICES; i++)
{
psDevIdList[i].eDeviceType = PVRSRV_DEVICE_TYPE_UNKNOWN;
}
-
+ /* and zero device count */
*pui32NumDevices = 0;
-
-
-
-
+ /*
+ Search through the device list for services managed devices
+ return id info for each device and the number of devices
+ available
+ */
List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
&PVRSRVEnumerateDevicesKM_ForEachVaCb,
pui32NumDevices,
@@ -202,11 +352,23 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVEnumerateDevicesKM(IMG_UINT32 *pui32NumDevices,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVInit
+
+ @Description Initialise services
+
+ @Input psSysData : sysdata structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
{
PVRSRV_ERROR eError;
-
+ /* Initialise Resource Manager */
eError = ResManInit();
if (eError != PVRSRV_OK)
{
@@ -219,25 +381,25 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
goto Error;
}
-
+ /* Initialise handles */
eError = PVRSRVHandleInit();
if(eError != PVRSRV_OK)
{
goto Error;
}
-
+ /* Initialise Power Manager Lock */
eError = OSCreateResource(&psSysData->sPowerStateChangeResource);
if (eError != PVRSRV_OK)
{
goto Error;
}
-
+ /* Initialise system power state */
psSysData->eCurrentPowerState = PVRSRV_SYS_POWER_STATE_D0;
psSysData->eFailedPowerState = PVRSRV_SYS_POWER_STATE_Unspecified;
-
+ /* Create an event object */
if(OSAllocMem( PVRSRV_PAGEABLE_SELECT,
sizeof(PVRSRV_EVENTOBJECT) ,
(IMG_VOID **)&psSysData->psGlobalEventObject, 0,
@@ -252,7 +414,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
goto Error;
}
-
+ /* Store OS high res timer fallbacks, the system is free to overide these */
psSysData->pfnHighResTimerCreate = OSFuncHighResTimerCreate;
psSysData->pfnHighResTimerGetus = OSFuncHighResTimerGetus;
psSysData->pfnHighResTimerDestroy = OSFuncHighResTimerDestroy;
@@ -264,10 +426,11 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData)
g_ui32InitFlags |= INIT_DATA_ENABLE_TTARCE;
#endif
-
+ /* Initialise pdump */
PDUMPINIT();
g_ui32InitFlags |= INIT_DATA_ENABLE_PDUMPINIT;
+ PERFINIT();
return eError;
Error:
@@ -277,6 +440,18 @@ Error:
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeInit
+
+ @Description De-Initialise services
+
+ @Input psSysData : sysdata structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
{
PVRSRV_ERROR eError;
@@ -288,20 +463,23 @@ IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeInit: PVRSRVHandleDeInit failed - invalid param"));
return;
}
+
+ PERFDEINIT();
+
#if defined(TTRACE)
-
+ /* deinitialise ttrace */
if ((g_ui32InitFlags & INIT_DATA_ENABLE_TTARCE) > 0)
{
PVRSRVTimeTraceDeinit();
}
#endif
-
+ /* deinitialise pdump */
if( (g_ui32InitFlags & INIT_DATA_ENABLE_PDUMPINIT) > 0)
{
PDUMPDEINIT();
}
-
+ /* destroy event object */
if(psSysData->psGlobalEventObject)
{
OSEventObjectDestroyKM(psSysData->psGlobalEventObject);
@@ -328,6 +506,26 @@ IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterDevice
+
+ @Description
+
+ registers a device with the system
+
+ @Input psSysData : sysdata structure
+
+ @Input pfnRegisterDevice : device registration function
+
+ @Input ui32SOCInterruptBit : SoC interrupt bit for this device
+
+ @Output pui32DeviceIndex : unique device key (for case of multiple identical devices)
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
PVRSRV_ERROR (*pfnRegisterDevice)(PVRSRV_DEVICE_NODE*),
IMG_UINT32 ui32SOCInterruptBit,
@@ -336,7 +534,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
PVRSRV_ERROR eError;
PVRSRV_DEVICE_NODE *psDeviceNode;
-
+ /* Allocate device node */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE),
(IMG_VOID **)&psDeviceNode, IMG_NULL,
@@ -352,33 +550,48 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVRegisterDevice(PSYS_DATA psSysData,
{
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
PVR_DPF((PVR_DBG_ERROR,"PVRSRVRegisterDevice : Failed to register device"));
return (PVRSRV_ERROR_DEVICE_REGISTER_FAILED);
}
-
-
-
-
-
+ /*
+ make the refcount 1 and test on this to initialise device
+ at acquiredevinfo. On release if refcount is 1, deinitialise
+ and when refcount is 0 (sysdata de-alloc) deallocate the device
+ structures
+ */
psDeviceNode->ui32RefCount = 1;
psDeviceNode->psSysData = psSysData;
psDeviceNode->ui32SOCInterruptBit = ui32SOCInterruptBit;
-
+ /* all devices need a unique identifier */
AllocateDeviceID(psSysData, &psDeviceNode->sDevId.ui32DeviceIndex);
-
+ /* and finally insert the device into the dev-list */
List_PVRSRV_DEVICE_NODE_Insert(&psSysData->psDeviceNodeList, psDeviceNode);
-
+ /* and copy back index */
*pui32DeviceIndex = psDeviceNode->sDevId.ui32DeviceIndex;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVInitialiseDevice
+
+ @Description
+
+ initialises device by index
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
{
PVRSRV_DEVICE_NODE *psDeviceNode;
@@ -389,7 +602,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
SysAcquireData(&psSysData);
-
+ /* Find device in the list */
psDeviceNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&MatchDeviceKM_AnyVaCb,
@@ -397,14 +610,19 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
IMG_TRUE);
if(!psDeviceNode)
{
-
+ /* Devinfo not in the list */
PVR_DPF((PVR_DBG_ERROR,"PVRSRVInitialiseDevice: requested device is not present"));
return PVRSRV_ERROR_INIT_FAILURE;
}
- PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+/*
+FoundDevice:
+*/
-
+ PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
+ /*
+ Create the device's resource manager context.
+ */
eError = PVRSRVResManConnect(IMG_NULL, &psDeviceNode->hResManContext);
if (eError != PVRSRV_OK)
{
@@ -412,7 +630,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
return eError;
}
-
+ /* Initialise the device */
if(psDeviceNode->pfnInitDevice != IMG_NULL)
{
eError = psDeviceNode->pfnInitDevice(psDeviceNode);
@@ -430,9 +648,17 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInitialiseDevice (IMG_UINT32 ui32DevIndex)
static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
+
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVPowerLock call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
+ return eError;
+ }
+
eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE_DEFAULT,
- KERNEL_ID, IMG_FALSE);
+ PVRSRV_DEV_POWER_STATE_DEFAULT);
+ PVRSRVPowerUnlock(KERNEL_ID);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVFinaliseSystem: Failed PVRSRVSetDevicePowerStateKM call (device index: %d)", psDeviceNode->sDevId.ui32DeviceIndex));
@@ -440,6 +666,7 @@ static PVRSRV_ERROR PVRSRVFinaliseSystem_SetPowerState_AnyCb(PVRSRV_DEVICE_NODE
return eError;
}
+/*wraps the PVRSRVDevInitCompatCheck call and prints a debugging message if failed*/
static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
@@ -452,8 +679,23 @@ static PVRSRV_ERROR PVRSRVFinaliseSystem_CompatCheck_AnyCb(PVRSRV_DEVICE_NODE *p
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVFinaliseSystem
+
+ @Description
+
+ Final part of system initialisation.
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
{
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
SYS_DATA *psSysData;
PVRSRV_ERROR eError;
@@ -470,7 +712,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
return eError;
}
-
+ /* Place all devices into their default power state. */
eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
&PVRSRVFinaliseSystem_SetPowerState_AnyCb);
if (eError != PVRSRV_OK)
@@ -478,7 +720,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
return eError;
}
-
+ /* Verify microkernel compatibility for devices */
eError = List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any(psSysData->psDeviceNodeList,
&PVRSRVFinaliseSystem_CompatCheck_AnyCb);
if (eError != PVRSRV_OK)
@@ -487,10 +729,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
}
}
-
-
-
-
+ /* Some platforms call this too early in the boot phase. */
#if !defined(__QNXNTO__)
PDUMPENDINITPHASE();
#endif
@@ -501,13 +740,34 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVFinaliseSystem(IMG_BOOL bInitSuccessful)
PVRSRV_ERROR PVRSRVDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
{
-
+ /* Only check devices which specify a compatibility check callback */
if (psDeviceNode->pfnInitDeviceCompatCheck)
return psDeviceNode->pfnInitDeviceCompatCheck(psDeviceNode);
else
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Matchs a device given a device type and a device index.
+
+ @input psDeviceNode :The device node to be matched.
+
+ @Input va : Variable argument list with:
+ eDeviceType : Required device type. If type is unknown use ui32DevIndex
+ to locate device data
+
+ ui32DevIndex : Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
PVRSRV_DEVICE_TYPE eDeviceType;
@@ -529,6 +789,27 @@ static IMG_VOID * PVRSRVAcquireDeviceDataKM_Match_AnyVaCb(PVRSRV_DEVICE_NODE *ps
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVAcquireDeviceDataKM
+
+ @Description
+
+ Returns device information
+
+ @Input ui32DevIndex : Index to the required device obtained from the
+ PVRSRVEnumerateDevice function
+
+ @Input eDeviceType : Required device type. If type is unknown use ui32DevIndex
+ to locate device data
+
+ @Output *phDevCookie : Dev Cookie
+
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
PVRSRV_DEVICE_TYPE eDeviceType,
@@ -541,7 +822,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
SysAcquireData(&psSysData);
-
+ /* Find device in the list */
psDeviceNode = List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
&PVRSRVAcquireDeviceDataKM_Match_AnyVaCb,
eDeviceType,
@@ -550,14 +831,16 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
if (!psDeviceNode)
{
-
+ /* device can't be found in the list so it isn't in the system */
PVR_DPF((PVR_DBG_ERROR,"PVRSRVAcquireDeviceDataKM: requested device is not present"));
return PVRSRV_ERROR_INIT_FAILURE;
}
+/*FoundDevice:*/
+
PVR_ASSERT (psDeviceNode->ui32RefCount > 0);
-
+ /* return the dev cookie? */
if (phDevCookie)
{
*phDevCookie = (IMG_HANDLE)psDeviceNode;
@@ -567,6 +850,20 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVAcquireDeviceDataKM (IMG_UINT32 ui32DevIndex,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeinitialiseDevice
+
+ @Description
+
+ This De-inits device
+
+ @Input ui32DevIndex : Index to the required device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
{
PVRSRV_DEVICE_NODE *psDeviceNode;
@@ -587,20 +884,28 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
return PVRSRV_ERROR_DEVICEID_NOT_FOUND;
}
-
+ eError = PVRSRVPowerLock(KERNEL_ID, IMG_FALSE);
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVPowerLock call"));
+ return eError;
+ }
+ /*
+ Power down the device if necessary.
+ */
eError = PVRSRVSetDevicePowerStateKM(ui32DevIndex,
- PVRSRV_DEV_POWER_STATE_OFF,
- KERNEL_ID,
- IMG_FALSE);
+ PVRSRV_DEV_POWER_STATE_OFF);
+ PVRSRVPowerUnlock(KERNEL_ID);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVDeinitialiseDevice: Failed PVRSRVSetDevicePowerStateKM call"));
return eError;
}
-
-
+ /*
+ Free the dissociated device memory.
+ */
eError = ResManFreeResByCriteria(psDeviceNode->hResManContext,
RESMAN_CRITERIA_RESTYPE,
RESMAN_TYPE_DEVICEMEM_ALLOCATION,
@@ -611,8 +916,9 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
return eError;
}
-
-
+ /*
+ De-init the device.
+ */
if(psDeviceNode->pfnDeInitDevice != IMG_NULL)
{
eError = psDeviceNode->pfnDeInitDevice(psDeviceNode);
@@ -623,19 +929,20 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex)
}
}
-
-
+ /*
+ Close the device's resource manager context.
+ */
PVRSRVResManDisconnect(psDeviceNode->hResManContext, IMG_TRUE);
psDeviceNode->hResManContext = IMG_NULL;
-
+ /* remove node from list */
List_PVRSRV_DEVICE_NODE_Remove(psDeviceNode);
-
+ /* deallocate id and memory */
(IMG_VOID)FreeDeviceID(psSysData, ui32DevIndex);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_DEVICE_NODE), psDeviceNode, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return (PVRSRV_OK);
}
@@ -656,8 +963,9 @@ PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
PVR_UNREFERENCED_PARAMETER(ui32PollPeriodus);
#endif
-
-
+ /* For the Emulator we want the system to stop when a lock-up is detected so the state can be analysed.
+ * Also the Emulator is much slower than real silicon so timeouts are not valid.
+ */
do
{
if((*pui32LinMemAddr & ui32Mask) == ui32Value)
@@ -671,18 +979,18 @@ PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
OSReleaseThreadQuanta();
#endif
- } while (ui32Timeoutus);
+ } while (ui32Timeoutus); /* Endless loop only for the Emulator */
}
#else
{
- IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU;
+ IMG_UINT32 ui32ActualValue = 0xFFFFFFFFU; /* Initialiser only required to prevent incorrect warning */
if (bAllowPreemption)
{
PVR_ASSERT(ui32PollPeriodus >= 1000);
}
-
+ /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
LOOP_UNTIL_TIMEOUT(ui32Timeoutus)
{
ui32ActualValue = (*pui32LinMemAddr & ui32Mask);
@@ -704,12 +1012,13 @@ PVRSRV_ERROR IMG_CALLCONV PollForValueKM (volatile IMG_UINT32* pui32LinMemAddr,
PVR_DPF((PVR_DBG_ERROR,"PollForValueKM: Timeout. Expected 0x%x but found 0x%x (mask 0x%x).",
ui32Value, ui32ActualValue, ui32Mask));
}
-#endif
+#endif /* #if defined (EMULATOR) */
return PVRSRV_ERROR_TIMEOUT;
}
+/*Level 3 of the loop nesting*/
static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, va_list va)
{
IMG_CHAR **ppszStr;
@@ -721,7 +1030,10 @@ static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, v
pui32StrLen = va_arg(va, IMG_UINT32*);
ui32Mode = va_arg(va, IMG_UINT32);
-
+ /* Would be better to pass fn pointer in the variable args list
+ * but MS C compiler complains with error C2066: In ANSI C,
+ * it is not legal to cast between a function pointer and a data pointer.
+ */
switch(ui32Mode)
{
case PVRSRV_MISC_INFO_MEMSTATS_PRESENT:
@@ -749,6 +1061,7 @@ static IMG_VOID PVRSRVGetMiscInfoKM_RA_GetStats_ForEachVaCb(BM_HEAP *psBMHeap, v
}
}
+/*Level 2 of the loop nesting*/
static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContext, va_list va)
{
@@ -776,6 +1089,7 @@ static PVRSRV_ERROR PVRSRVGetMiscInfoKM_BMContext_AnyVaCb(BM_CONTEXT *psBMContex
}
+/*level 1 of the loop nesting*/
static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, va_list va)
{
IMG_UINT32 *pui32StrLen;
@@ -792,7 +1106,7 @@ static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDev
*pi32Count = OSSNPrintf(*ppszStr, 100, "\n\nDevice Type %d:\n", psDeviceNode->sDevId.eDeviceType);
UPDATE_SPACE(*ppszStr, *pi32Count, *pui32StrLen);
-
+ /* kernel context: */
if(psDeviceNode->sDevMemoryInfo.pBMKernelContext)
{
CHECK_SPACE(*pui32StrLen);
@@ -806,7 +1120,7 @@ static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDev
ui32Mode);
}
-
+ /* double loop app contexts:heaps */
return List_BM_CONTEXT_PVRSRV_ERROR_Any_va(psDeviceNode->sDevMemoryInfo.pBMContext,
&PVRSRVGetMiscInfoKM_BMContext_AnyVaCb,
pui32StrLen,
@@ -816,6 +1130,19 @@ static PVRSRV_ERROR PVRSRVGetMiscInfoKM_Device_AnyVaCb(PVRSRV_DEVICE_NODE *psDev
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVGetMiscInfoKM
+
+ @Description
+ Retrieves misc. info.
+
+ @Output PVRSRV_MISC_INFO
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO_KM *psMiscInfo)
@@ -833,7 +1160,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
psMiscInfo->ui32StatePresent = 0;
-
+ /* do a basic check for uninitialised request flag */
if(psMiscInfo->ui32StateRequest & ~(PVRSRV_MISC_INFO_TIMER_PRESENT
|PVRSRV_MISC_INFO_CLOCKGATE_PRESENT
|PVRSRV_MISC_INFO_MEMSTATS_PRESENT
@@ -841,7 +1168,10 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
|PVRSRV_MISC_INFO_DDKVERSION_PRESENT
|PVRSRV_MISC_INFO_CPUCACHEOP_PRESENT
|PVRSRV_MISC_INFO_RESET_PRESENT
- |PVRSRV_MISC_INFO_FREEMEM_PRESENT))
+ |PVRSRV_MISC_INFO_FREEMEM_PRESENT
+ |PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT
+ |PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT
+ |PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT))
{
PVR_DPF((PVR_DBG_ERROR,"PVRSRVGetMiscInfoKM: invalid state request flags"));
return PVRSRV_ERROR_INVALID_PARAMS;
@@ -849,7 +1179,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
SysAcquireData(&psSysData);
-
+ /* return SOC Timer registers */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_TIMER_PRESENT) != 0UL) &&
(psSysData->pvSOCTimerRegisterKM != IMG_NULL))
{
@@ -863,7 +1193,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
psMiscInfo->hSOCTimerRegisterOSMemHandle = IMG_NULL;
}
-
+ /* return SOC Clock Gating registers */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_CLOCKGATE_PRESENT) != 0UL) &&
(psSysData->pvSOCClockGateRegsBase != IMG_NULL))
{
@@ -872,11 +1202,14 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
psMiscInfo->ui32SOCClockGateRegsSize = psSysData->ui32SOCClockGateRegsSize;
}
-
+ /* memory stats */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) != 0UL) &&
(psMiscInfo->pszMemoryStr != IMG_NULL))
{
RA_ARENA **ppArena;
+/* BM_HEAP *psBMHeap;
+ BM_CONTEXT *psBMContext;
+ PVRSRV_DEVICE_NODE *psDeviceNode;*/
IMG_CHAR *pszStr;
IMG_UINT32 ui32StrLen;
IMG_INT32 i32Count;
@@ -886,7 +1219,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_MEMSTATS_PRESENT;
-
+ /* Local backing stores */
ppArena = &psSysData->apsLocalDevMemArena[0];
while(*ppArena)
{
@@ -897,12 +1230,14 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
RA_GetStats(*ppArena,
&pszStr,
&ui32StrLen);
-
+ /* advance through the array */
ppArena++;
}
-
-
+ /* per device */
+/* psDeviceNode = psSysData->psDeviceNodeList;*/
+
+ /*triple loop; devices:contexts:heaps*/
List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
&ui32StrLen,
@@ -910,12 +1245,12 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
&pszStr,
PVRSRV_MISC_INFO_MEMSTATS_PRESENT);
-
+ /* attach a new line and string terminate */
i32Count = OSSNPrintf(pszStr, 100, "\n");
UPDATE_SPACE(pszStr, i32Count, ui32StrLen);
}
-
+ /* Lean version of mem stats: only show free mem on each RA */
if(((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FREEMEM_PRESENT) != 0)
&& psMiscInfo->pszMemoryStr)
{
@@ -928,7 +1263,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FREEMEM_PRESENT;
-
+ /* triple loop over devices:contexts:heaps */
List_PVRSRV_DEVICE_NODE_PVRSRV_ERROR_Any_va(psSysData->psDeviceNodeList,
&PVRSRVGetMiscInfoKM_Device_AnyVaCb,
&ui32StrLen,
@@ -947,7 +1282,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
psMiscInfo->sGlobalEventObject = *psSysData->psGlobalEventObject;
}
-
+ /* DDK version and memstats not supported in same call to GetMiscInfo */
if (((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_DDKVERSION_PRESENT) != 0UL)
&& ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_MEMSTATS_PRESENT) == 0UL)
@@ -955,16 +1290,16 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
{
IMG_CHAR *pszStr;
IMG_UINT32 ui32StrLen;
- IMG_UINT32 ui32LenStrPerNum = 12;
+ IMG_UINT32 ui32LenStrPerNum = 12; /* string length per UI32: 10 digits + '.' + '\0' = 12 bytes */
IMG_INT32 i32Count;
IMG_INT i;
psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_DDKVERSION_PRESENT;
-
+ /* construct DDK string */
psMiscInfo->aui32DDKVersion[0] = PVRVERSION_MAJ;
psMiscInfo->aui32DDKVersion[1] = PVRVERSION_MIN;
- psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BRANCH;
- psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD;
+ psMiscInfo->aui32DDKVersion[2] = PVRVERSION_BUILD_HI;
+ psMiscInfo->aui32DDKVersion[3] = PVRVERSION_BUILD_LO;
pszStr = psMiscInfo->pszMemoryStr;
ui32StrLen = psMiscInfo->ui32MemoryStrLen;
@@ -992,7 +1327,9 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
if(psMiscInfo->sCacheOpCtl.bDeferOp)
{
-
+ /* For now, assume deferred ops are "full" cache ops,
+ * and we don't need (or expect) a meminfo.
+ */
psSysData->ePendingCacheOpType = psMiscInfo->sCacheOpCtl.eCacheOpType;
}
else
@@ -1023,7 +1360,6 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
#if defined (SUPPORT_SID_INTERFACE)
PVR_DBG_BREAK
#else
-
psPerProc = PVRSRVFindPerProcessData();
if(PVRSRVLookupHandle(psPerProc->psHandleBase,
@@ -1040,6 +1376,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
{
if(!OSFlushCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ 0,
psMiscInfo->sCacheOpCtl.pvBaseVAddr,
psMiscInfo->sCacheOpCtl.ui32Length))
{
@@ -1050,7 +1387,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
if ((psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN_REGIONS) ||
(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_INV_REGIONS))
{
- IMG_BOOL (*op)(IMG_HANDLE hOSMemHandle, IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length);
+ IMG_BOOL (*op)(IMG_HANDLE hOSMemHandle, IMG_UINT32 ui32ByteOffset, IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length);
IMG_HANDLE hOSMemHandle = psKernelMemInfo->sMemBlk.hOSMemHandle;
IMG_VOID *pvEndVAddr = psMiscInfo->sCacheOpCtl.pvBaseVAddr +
psMiscInfo->sCacheOpCtl.ui32Length;
@@ -1075,7 +1412,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
ui32Length *= psMiscInfo->sCacheOpCtl.sRegions[i].h;
- if(!(*op)(hOSMemHandle, pvBaseVAddr, ui32Length))
+ if(!(*op)(hOSMemHandle, 0, pvBaseVAddr, ui32Length))
{
return PVRSRV_ERROR_CACHEOP_FAILED;
}
@@ -1099,7 +1436,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
ui32Length = pvEndVAddr - pvBaseVAddr;
}
- if(!(*op)(hOSMemHandle, pvBaseVAddr, ui32Length))
+ if(!(*op)(hOSMemHandle, 0, pvBaseVAddr, ui32Length))
{
printk(KERN_WARNING "op failed\n");
return PVRSRV_ERROR_CACHEOP_FAILED;
@@ -1115,6 +1452,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
else if(psMiscInfo->sCacheOpCtl.eCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_CLEAN)
{
if(!OSCleanCPUCacheRangeKM(psKernelMemInfo->sMemBlk.hOSMemHandle,
+ 0,
psMiscInfo->sCacheOpCtl.pvBaseVAddr,
psMiscInfo->sCacheOpCtl.ui32Length))
{
@@ -1256,18 +1594,71 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetMiscInfoKM(PVRSRV_MISC_INFO *psMiscInfo)
}
}
+ if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT) != 0UL)
+ {
+#if !defined (SUPPORT_SID_INTERFACE)
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+ PVRSRV_PER_PROCESS_DATA *psPerProc;
+#endif
+
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_REF_COUNT_PRESENT;
+
+#if defined (SUPPORT_SID_INTERFACE)
+ PVR_DBG_BREAK
+#else
+ psPerProc = PVRSRVFindPerProcessData();
+
+ if(PVRSRVLookupHandle(psPerProc->psHandleBase,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psMiscInfo->sGetRefCountCtl.u.psKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVGetMiscInfoKM: "
+ "Can't find kernel meminfo"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ psMiscInfo->sGetRefCountCtl.ui32RefCount = psKernelMemInfo->ui32RefCount;
+#endif
+ }
+
+ if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT) != 0UL)
+ {
+ psMiscInfo->ui32PageSize = HOST_PAGESIZE();
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_GET_PAGE_SIZE_PRESENT;
+ }
+
#if defined(PVRSRV_RESET_ON_HWTIMEOUT)
if((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_RESET_PRESENT) != 0UL)
{
PVR_LOG(("User requested OS reset"));
OSPanic();
}
-#endif
+#endif /* #if defined(PVRSRV_RESET_ON_HWTIMEOUT) */
+
+ if ((psMiscInfo->ui32StateRequest & PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT) != 0UL)
+ {
+ PVRSRVSetDCState(DC_STATE_FORCE_SWAP_TO_SYSTEM);
+ psMiscInfo->ui32StatePresent |= PVRSRV_MISC_INFO_FORCE_SWAP_TO_SYSTEM_PRESENT;
+ }
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDeviceLISR
+
+ @Description
+ OS-independent Device Low-level Interrupt Service Routine
+
+ @Input psDeviceNode
+
+ @Return IMG_BOOL : Whether any interrupts were serviced
+
+******************************************************************************/
IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
{
SYS_DATA *psSysData;
@@ -1281,7 +1672,7 @@ IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode)
}
psSysData = psDeviceNode->psSysData;
-
+ /* query the SOC/system to see whether this device was the source of the interrupt */
ui32InterruptSource = SysGetInterruptSource(psSysData, psDeviceNode);
if(ui32InterruptSource & psDeviceNode->ui32SOCInterruptBit)
{
@@ -1315,34 +1706,50 @@ static IMG_VOID PVRSRVSystemLISR_ForEachVaCb(PVRSRV_DEVICE_NODE *psDeviceNode, v
{
if((*psDeviceNode->pfnDeviceISR)(psDeviceNode->pvISRData))
{
-
+ /* Record if serviced any interrupts. */
*pbStatus = IMG_TRUE;
}
-
+ /* Combine the SOC clear bits. */
*pui32ClearInterrupts |= psDeviceNode->ui32SOCInterruptBit;
}
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSystemLISR
+
+ @Description
+ OS-independent System Low-level Interrupt Service Routine
+
+ @Input pvSysData
+
+ @Return IMG_BOOL : Whether any interrupts were serviced
+
+******************************************************************************/
IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = pvSysData;
IMG_BOOL bStatus = IMG_FALSE;
IMG_UINT32 ui32InterruptSource;
IMG_UINT32 ui32ClearInterrupts = 0;
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
+
if(!psSysData)
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVSystemLISR: Invalid params\n"));
+/* goto out; */
}
else
{
-
+ /* query SOC for source of interrupts */
ui32InterruptSource = SysGetInterruptSource(psSysData, IMG_NULL);
-
+ /* only proceed if PVR interrupts */
if(ui32InterruptSource)
{
-
+ /* traverse the devices' ISR handlers */
List_PVRSRV_DEVICE_NODE_ForEach_va(psSysData->psDeviceNodeList,
&PVRSRVSystemLISR_ForEachVaCb,
&bStatus,
@@ -1351,6 +1758,7 @@ IMG_BOOL IMG_CALLCONV PVRSRVSystemLISR(IMG_VOID *pvSysData)
SysClearInterrupts(psSysData, ui32ClearInterrupts);
}
+/*out:*/
}
return bStatus;
}
@@ -1364,9 +1772,21 @@ static IMG_VOID PVRSRVMISR_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVMISR
+
+ @Input pvSysData
+
+ @Description
+ OS-independent Medium-level Interrupt Service Routine
+
+******************************************************************************/
IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = pvSysData;
+/* PVRSRV_DEVICE_NODE *psDeviceNode; */
#ifdef SUPPORT_DRI_DRM_EXTERNAL
omap_gem_op_update();
@@ -1378,17 +1798,17 @@ IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
return;
}
-
+ /* Traverse the devices' MISR handlers. */
List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
&PVRSRVMISR_ForEachCb);
-
+ /* Process the queues. */
if (PVRSRVProcessQueues(IMG_FALSE) == PVRSRV_ERROR_PROCESSING_BLOCKED)
{
PVRSRVProcessQueues(IMG_FALSE);
}
-
+ /* signal global event object */
if (psSysData->psGlobalEventObject)
{
IMG_HANDLE hOSEventKM = psSysData->psGlobalEventObject->hOSEventKM;
@@ -1400,6 +1820,18 @@ IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessConnect
+
+ @Description Inform services that a process has connected.
+
+ @Input ui32PID - process ID
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui32Flags)
{
@@ -1407,6 +1839,18 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVProcessConnect(IMG_UINT32 ui32PID, IMG_UINT32 ui
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessDisconnect
+
+ @Description Inform services that a process has disconnected.
+
+ @Input ui32PID - process ID
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
{
@@ -1414,6 +1858,20 @@ IMG_VOID IMG_CALLCONV PVRSRVProcessDisconnect(IMG_UINT32 ui32PID)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVSaveRestoreLiveSegments
+
+ @Input pArena - the arena the segment was originally allocated from.
+ pbyBuffer - the system memory buffer set to null to get the size needed.
+ puiBufSize - size of system memory buffer.
+ bSave - IMG_TRUE if a save is required
+
+ @Description
+ Function to save or restore Resources Live segments
+
+******************************************************************************/
PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_PBYTE pbyBuffer,
IMG_SIZE_T *puiBufSize, IMG_BOOL bSave)
{
@@ -1430,12 +1888,12 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_P
sSegDetails.sCpuPhyAddr.uiAddr = 0;
sSegDetails.hSegment = 0;
-
+ /* walk the arena segments and write live one to the buffer */
while (RA_GetNextLiveSegment(hArena, &sSegDetails))
{
if (pbyBuffer == IMG_NULL)
{
-
+ /* calc buffer required */
uiBytesSaved += sizeof(sSegDetails.uiSize) + sSegDetails.uiSize;
}
else
@@ -1447,7 +1905,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_P
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVSaveRestoreLiveSegments: Base %08x size %08x", sSegDetails.sCpuPhyAddr.uiAddr, sSegDetails.uiSize));
-
+ /* Map the device's local memory area onto the host. */
pvLocalMemCPUVAddr = OSMapPhysToLin(sSegDetails.sCpuPhyAddr,
sSegDetails.uiSize,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
@@ -1460,7 +1918,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_P
if (bSave)
{
-
+ /* write segment size then segment data */
OSMemCopy(pbyBuffer, &sSegDetails.uiSize, sizeof(sSegDetails.uiSize));
pbyBuffer += sizeof(sSegDetails.uiSize);
@@ -1470,7 +1928,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_P
else
{
IMG_UINT32 uiSize;
-
+ /* reag segment size and validate */
OSMemCopy(&uiSize, pbyBuffer, sizeof(sSegDetails.uiSize));
if (uiSize != sSegDetails.uiSize)
@@ -1505,10 +1963,28 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVSaveRestoreLiveSegments(IMG_HANDLE hArena, IMG_P
}
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorStringKM
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ @Note case statement used rather than an indexed arrary to ensure text is
+ synchronised with the correct enum
+
+ @Input eError : PVRSRV_ERROR enum
+
+ @Return const IMG_CHAR * : Text string
+
+ @Note Must be kept in sync with servicesext.h
+
+******************************************************************************/
+
IMG_EXPORT
const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError)
{
-
+/* PRQA S 5087 1 */ /* include file required here */
#include "pvrsrv_errors.h"
}
@@ -1516,23 +1992,52 @@ static IMG_VOID PVRSRVCommandCompleteCallbacks_ForEachCb(PVRSRV_DEVICE_NODE *psD
{
if(psDeviceNode->pfnDeviceCommandComplete != IMG_NULL)
{
-
+ /* Call the device's callback function. */
(*psDeviceNode->pfnDeviceCommandComplete)(psDeviceNode);
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVScheduleDeviceCallbacks
+
+ @Description Schedule all device callbacks
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVScheduleDeviceCallbacks(IMG_VOID)
{
SYS_DATA *psSysData;
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
+
SysAcquireData(&psSysData);
-
+ /*for all the device, invoke the callback function*/
List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
&PVRSRVCommandCompleteCallbacks_ForEachCb);
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVScheduleDevices
+
+ @Description Schedules all Services-Managed Devices to check their pending
+ command queues. The intention is that ScheduleDevices be called by the
+ 3rd party BC driver after it has finished writing new data to its output
+ texture.
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVScheduleDevicesKM(IMG_VOID)
{
PVRSRVScheduleDeviceCallbacks();
}
+
+/*****************************************************************************
+ End of file (pvrsrv.c)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/common/queue.c b/sgx/services4/srvkm/common/queue.c
index 5a1e9b4..762c952 100644
--- a/sgx/services4/srvkm/common/queue.c
+++ b/sgx/services4/srvkm/common/queue.c
@@ -1,41 +1,73 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Kernel side command queue functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
+#include "pvr_bridge_km.h"
#include "lists.h"
#include "ttrace.h"
+/*
+ * The number of commands of each type which can be in flight at once.
+ */
+#if defined(SUPPORT_DC_CMDCOMPLETE_WHEN_NO_LONGER_DISPLAYED)
+#define DC_NUM_COMMANDS_PER_TYPE 2
+#else
#define DC_NUM_COMMANDS_PER_TYPE 1
-
+#endif
+
+/*
+ * List of private command processing function pointer tables and command
+ * complete tables for a device in the system.
+ * Each table is allocated when the device registers its private command
+ * processing functions.
+ */
typedef struct _DEVICE_COMMAND_DATA_
{
PFN_CMD_PROC pfnCmdProc;
PCOMMAND_COMPLETE_DATA apsCmdCompleteData[DC_NUM_COMMANDS_PER_TYPE];
IMG_UINT32 ui32CCBOffset;
+ IMG_UINT32 ui32MaxDstSyncCount; /*!< Maximum number of dest syncs */
+ IMG_UINT32 ui32MaxSrcSyncCount; /*!< Maximum number of source syncs */
} DEVICE_COMMAND_DATA;
@@ -43,6 +75,15 @@ typedef struct _DEVICE_COMMAND_DATA_
#include "proc.h"
+/*****************************************************************************
+ FUNCTION : ProcSeqShowQueue
+
+ PURPOSE : Print the content of queue element to /proc file
+ (See env/linux/proc.c:CreateProcReadEntrySeq)
+
+ PARAMETERS : sfile - /proc seq_file
+ el - Element to print
+*****************************************************************************/
void ProcSeqShowQueue(struct seq_file *sfile,void* el)
{
PVRSRV_QUEUE_INFO *psQueue = (PVRSRV_QUEUE_INFO*)el;
@@ -83,16 +124,16 @@ void ProcSeqShowQueue(struct seq_file *sfile,void* el)
PVRSRV_SYNC_DATA *psSyncData = psCmd->psSrcSync[i].psKernelSyncInfoKM->psSyncData;
seq_printf(sfile, " Sync %u: ROP/ROC: 0x%x/0x%x WOP/WOC: 0x%x/0x%x ROC-VA: 0x%x WOC-VA: 0x%x\n",
i,
- psCmd->psSrcSync[i].ui32ReadOpsPending,
- psSyncData->ui32ReadOpsComplete,
+ psCmd->psSrcSync[i].ui32ReadOps2Pending,
+ psSyncData->ui32ReadOps2Complete,
psCmd->psSrcSync[i].ui32WriteOpsPending,
psSyncData->ui32WriteOpsComplete,
- psCmd->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ psCmd->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmd->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr);
}
}
-
+ /* taken from UPDATE_QUEUE_ROFF in queue.h */
ui32ReadOffset += psCmd->uCmdSize;
ui32ReadOffset &= psQueue->ui32QueueSize - 1;
cmds++;
@@ -104,6 +145,16 @@ void ProcSeqShowQueue(struct seq_file *sfile,void* el)
}
}
+/*****************************************************************************
+ FUNCTION : ProcSeqOff2ElementQueue
+
+ PURPOSE : Transale offset to element (/proc stuff)
+
+ PARAMETERS : sfile - /proc seq_file
+ off - the offset into the buffer
+
+ RETURNS : element to print
+*****************************************************************************/
void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
{
PVRSRV_QUEUE_INFO *psQueue = IMG_NULL;
@@ -125,19 +176,94 @@ void* ProcSeqOff2ElementQueue(struct seq_file * sfile, loff_t off)
return psQueue;
}
-#endif
+#endif /* __linux__ && __KERNEL__ */
+/*!
+ * Macro to return space in given command queue
+ */
#define GET_SPACE_IN_CMDQ(psQueue) \
((((psQueue)->ui32ReadOffset - (psQueue)->ui32WriteOffset) \
+ ((psQueue)->ui32QueueSize - 1)) & ((psQueue)->ui32QueueSize - 1))
+/*!
+ * Macro to Write Offset in given command queue
+ */
#define UPDATE_QUEUE_WOFF(psQueue, ui32Size) \
(psQueue)->ui32WriteOffset = ((psQueue)->ui32WriteOffset + (ui32Size)) \
& ((psQueue)->ui32QueueSize - 1);
+/*!
+ * Check if an ops complete value has gone past the pending value.
+ * This can happen when dummy processing multiple operations, e.g. hardware recovery.
+ */
#define SYNCOPS_STALE(ui32OpsComplete, ui32OpsPending) \
((ui32OpsComplete) >= (ui32OpsPending))
+/*!
+****************************************************************************
+ @Function : PVRSRVGetWriteOpsPending
+
+ @Description : Gets the next operation to wait for in a sync object
+
+ @Input : psSyncInfo - pointer to sync information struct
+ @Input : bIsReadOp - Is this a read or write op
+
+ @Return : Next op value
+*****************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetWriteOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetWriteOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32WriteOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending;
+ }
+ else
+ {
+ /*
+ Note: This needs to be atomic and is provided the
+ kernel driver is single threaded (non-rentrant)
+ */
+ ui32WriteOpsPending = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ }
+
+ return ui32WriteOpsPending;
+}
+
+/*!
+*****************************************************************************
+ @Function : PVRSRVGetReadOpsPending
+
+ @Description : Gets the number of pending read ops
+
+ @Input : psSyncInfo - pointer to sync information struct
+ @Input : bIsReadOp - Is this a read or write op
+
+ @Return : Next op value
+*****************************************************************************/
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(PVRSRVGetReadOpsPending)
+#endif
+static INLINE
+IMG_UINT32 PVRSRVGetReadOpsPending(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo, IMG_BOOL bIsReadOp)
+{
+ IMG_UINT32 ui32ReadOpsPending;
+
+ if(bIsReadOp)
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOps2Pending++;
+ }
+ else
+ {
+ ui32ReadOpsPending = psSyncInfo->psSyncData->ui32ReadOps2Pending;
+ }
+
+ return ui32ReadOpsPending;
+}
static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
IMG_UINT32 i,
@@ -151,9 +277,9 @@ static IMG_VOID QueueDumpCmdComplete(COMMAND_COMPLETE_DATA *psCmdCompleteData,
{
PVR_LOG(("\t%s %u: ROC DevVAddr:0x%X ROP:0x%x ROC:0x%x, WOC DevVAddr:0x%X WOP:0x%x WOC:0x%x",
bIsSrc ? "SRC" : "DEST", i,
- psSyncObject[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
- psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsPending,
- psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete,
+ psSyncObject[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Pending,
+ psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete,
psSyncObject[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsPending,
psSyncObject[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete))
@@ -218,6 +344,10 @@ IMG_VOID QueueDumpDebugInfo(IMG_VOID)
}
+/*****************************************************************************
+ Kernel-side functions of User->Kernel transitions
+******************************************************************************/
+
static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
{
IMG_SIZE_T ui32Temp, ui32Result = 1;
@@ -236,6 +366,22 @@ static IMG_SIZE_T NearestPower2(IMG_SIZE_T ui32Value)
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVCreateCommandQueueKM
+
+ @Description
+ Creates a new command queue into which render/blt commands etc can be
+ inserted.
+
+ @Input ui32QueueSize :
+
+ @Output ppsQueueInfo :
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
PVRSRV_QUEUE_INFO **ppsQueueInfo)
@@ -248,7 +394,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
SysAcquireData(&psSysData);
-
+ /* allocate an internal queue info structure */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_QUEUE_INFO),
(IMG_VOID **)&psQueueInfo, &hMemBlock,
@@ -263,7 +409,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
psQueueInfo->hMemBlock[0] = hMemBlock;
psQueueInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
-
+ /* allocate the command queue buffer - allow for overrun */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
ui32Power2QueueSize + PVRSRV_MAX_CMD_SIZE,
&psQueueInfo->pvLinQueueKM, &hMemBlock,
@@ -277,13 +423,13 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
psQueueInfo->hMemBlock[1] = hMemBlock;
psQueueInfo->pvLinQueueUM = psQueueInfo->pvLinQueueKM;
-
+ /* Sanity check: Should be zeroed by OSMemSet */
PVR_ASSERT(psQueueInfo->ui32ReadOffset == 0);
PVR_ASSERT(psQueueInfo->ui32WriteOffset == 0);
psQueueInfo->ui32QueueSize = ui32Power2QueueSize;
-
+ /* if this is the first q, create a lock resource for the q list */
if (psSysData->psQueueList == IMG_NULL)
{
eError = OSCreateResource(&psSysData->sQProcessResource);
@@ -293,7 +439,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVCreateCommandQueueKM(IMG_SIZE_T ui32QueueSize,
}
}
-
+ /* Ensure we don't corrupt queue list, by blocking access */
eError = OSLockResource(&psSysData->sQProcessResource,
KERNEL_ID);
if (eError != PVRSRV_OK)
@@ -331,13 +477,25 @@ ErrorExit:
sizeof(PVRSRV_QUEUE_INFO),
psQueueInfo,
psQueueInfo->hMemBlock[0]);
-
+ /*not nulling pointer, out of scope*/
}
return eError;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDestroyCommandQueueKM
+
+ @Description Destroys a command queue
+
+ @Input psQueueInfo :
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueueInfo)
{
@@ -350,7 +508,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueue
psQueue = psSysData->psQueueList;
-
+ /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
{
if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
@@ -363,13 +521,14 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueue
if (bTimeout)
{
-
+ /* The command queue could not be flushed within the timeout period.
+ Allow the queue to be destroyed before returning the error code. */
PVR_DPF((PVR_DBG_ERROR,"PVRSRVDestroyCommandQueueKM : Failed to empty queue"));
eError = PVRSRV_ERROR_CANNOT_FLUSH_QUEUE;
goto ErrorExit;
}
-
+ /* Ensure we don't corrupt queue list, by blocking access */
eError = OSLockResource(&psSysData->sQProcessResource,
KERNEL_ID);
if (eError != PVRSRV_OK)
@@ -390,8 +549,8 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueue
sizeof(PVRSRV_QUEUE_INFO),
psQueueInfo,
psQueueInfo->hMemBlock[0]);
-
- psQueueInfo = IMG_NULL;
+ /* PRQA S 3199 1 */ /* see note */
+ psQueueInfo = IMG_NULL; /*it's a copy on stack, but null it because the function doesn't end right here*/
}
else
{
@@ -410,8 +569,8 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueue
sizeof(PVRSRV_QUEUE_INFO),
psQueueInfo,
psQueueInfo->hMemBlock[0]);
-
- psQueueInfo = IMG_NULL;
+ /* PRQA S 3199 1 */ /* see note */
+ psQueueInfo = IMG_NULL; /*it's a copy on stack, but null it because the function doesn't end right here*/
break;
}
psQueue = psQueue->psNextKM;
@@ -429,14 +588,14 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDestroyCommandQueueKM(PVRSRV_QUEUE_INFO *psQueue
}
}
-
+ /* unlock the Q list lock resource */
eError = OSUnlockResource(&psSysData->sQProcessResource, KERNEL_ID);
if (eError != PVRSRV_OK)
{
goto ErrorExit;
}
-
+ /* if the Q list is now empty, destroy the Q list lock resource */
if (psSysData->psQueueList == IMG_NULL)
{
eError = OSDestroyResource(&psSysData->sQProcessResource);
@@ -452,6 +611,20 @@ ErrorExit:
}
+/*!
+*****************************************************************************
+
+ @Function : PVRSRVGetQueueSpaceKM
+
+ @Description : Waits for queue access rights and checks for available space in
+ queue for task param structure
+
+ @Input : psQueue - pointer to queue information struct
+ @Input : ui32ParamSize - size of task data structure
+ @Output : ppvSpace
+
+ @Return : PVRSRV_ERROR
+*****************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
IMG_SIZE_T ui32ParamSize,
@@ -459,7 +632,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
{
IMG_BOOL bTimeout = IMG_TRUE;
-
+ /* round to 4byte units */
ui32ParamSize = (ui32ParamSize+3) & 0xFFFFFFFC;
if (ui32ParamSize > PVRSRV_MAX_CMD_SIZE)
@@ -468,7 +641,7 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
return PVRSRV_ERROR_CMD_TOO_BIG;
}
-
+ /* PRQA S 3415,4109 1 */ /* macro format critical - leave alone */
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
{
if (GET_SPACE_IN_CMDQ(psQueue) > ui32ParamSize)
@@ -494,6 +667,26 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
}
+/*!
+*****************************************************************************
+ @Function PVRSRVInsertCommandKM
+
+ @Description :
+ command insertion utility
+ - waits for space in the queue for a new command
+ - fills in generic command information
+ - returns a pointer to the caller who's expected to then fill
+ in the private data.
+ The caller should follow PVRSRVInsertCommand with PVRSRVSubmitCommand
+ which will update the queue's write offset so the command can be
+ executed.
+
+ @Input psQueue : pointer to queue information struct
+
+ @Output ppvCmdData : holds pointer to space in queue for private cmd data
+
+ @Return PVRSRV_ERROR
+*****************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_COMMAND **ppsCommand,
@@ -503,22 +696,37 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
IMG_UINT32 ui32SrcSyncCount,
PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
- IMG_SIZE_T ui32DataByteSize )
+ IMG_SIZE_T ui32DataByteSize,
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+ IMG_HANDLE hCallbackData)
{
PVRSRV_ERROR eError;
PVRSRV_COMMAND *psCommand;
IMG_SIZE_T ui32CommandSize;
IMG_UINT32 i;
+ SYS_DATA *psSysData;
+ DEVICE_COMMAND_DATA *psDeviceCommandData;
-
+ /* Check that we've got enough space in our command complete data for this command */
+ SysAcquireData(&psSysData);
+ psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
+
+ if ((psDeviceCommandData[CommandType].ui32MaxDstSyncCount < ui32DstSyncCount) ||
+ (psDeviceCommandData[CommandType].ui32MaxSrcSyncCount < ui32SrcSyncCount))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVInsertCommandKM: Too many syncs"));
+ return PVRSRV_ERROR_INVALID_PARAMS;
+ }
+
+ /* Round up to nearest 32 bit size so pointer arithmetic works */
ui32DataByteSize = (ui32DataByteSize + 3UL) & ~3UL;
-
+ /* calc. command size */
ui32CommandSize = sizeof(PVRSRV_COMMAND)
+ ((ui32DstSyncCount + ui32SrcSyncCount) * sizeof(PVRSRV_SYNC_OBJECT))
+ ui32DataByteSize;
-
+ /* wait for space in queue */
eError = PVRSRVGetQueueSpaceKM (psQueue, ui32CommandSize, (IMG_VOID**)&psCommand);
if(eError != PVRSRV_OK)
{
@@ -527,14 +735,14 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
psCommand->ui32ProcessID = OSGetCurrentProcessIDKM();
-
- psCommand->uCmdSize = ui32CommandSize;
+ /* setup the command */
+ psCommand->uCmdSize = ui32CommandSize; /* this may change if cmd shrinks */
psCommand->ui32DevIndex = ui32DevIndex;
psCommand->CommandType = CommandType;
psCommand->ui32DstSyncCount = ui32DstSyncCount;
psCommand->ui32SrcSyncCount = ui32SrcSyncCount;
-
-
+ /* override QAC warning about stricter pointers */
+ /* PRQA S 3305 END_PTR_ASSIGNMENTS */
psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand) + sizeof(PVRSRV_COMMAND));
@@ -543,13 +751,18 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
psCommand->pvData = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psCommand->psSrcSync)
+ (ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
- psCommand->uDataSize = ui32DataByteSize;
+/* PRQA L:END_PTR_ASSIGNMENTS */
+
+ psCommand->uDataSize = ui32DataByteSize;/* this may change if cmd shrinks */
+
+ psCommand->pfnCommandComplete = pfnCommandComplete;
+ psCommand->hCallbackData = hCallbackData;
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_START, QUEUE_TOKEN_INSERTKM);
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_NONE,
QUEUE_TOKEN_COMMAND_TYPE, CommandType);
-
+ /* setup dst sync objects and their sync dependencies */
for (i=0; i<ui32DstSyncCount; i++)
{
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
@@ -557,16 +770,18 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
psCommand->psDstSync[i].psKernelSyncInfoKM = apsDstSync[i];
psCommand->psDstSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsDstSync[i], IMG_FALSE);
- psCommand->psDstSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+ psCommand->psDstSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsDstSync[i], IMG_FALSE);
+
+ PVRSRVKernelSyncInfoIncRef(apsDstSync[i], IMG_NULL);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCommand->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCommand->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCommand->psDstSync[i].ui32ReadOpsPending,
+ psCommand->psDstSync[i].ui32ReadOps2Pending,
psCommand->psDstSync[i].ui32WriteOpsPending));
}
-
+ /* setup src sync objects and their sync dependencies */
for (i=0; i<ui32SrcSyncCount; i++)
{
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_DST_SYNC,
@@ -574,30 +789,44 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
psCommand->psSrcSync[i].psKernelSyncInfoKM = apsSrcSync[i];
psCommand->psSrcSync[i].ui32WriteOpsPending = PVRSRVGetWriteOpsPending(apsSrcSync[i], IMG_TRUE);
- psCommand->psSrcSync[i].ui32ReadOpsPending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+ psCommand->psSrcSync[i].ui32ReadOps2Pending = PVRSRVGetReadOpsPending(apsSrcSync[i], IMG_TRUE);
+
+ PVRSRVKernelSyncInfoIncRef(apsSrcSync[i], IMG_NULL);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVInsertCommandKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCommand->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCommand->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCommand->psSrcSync[i].ui32ReadOpsPending,
+ psCommand->psSrcSync[i].ui32ReadOps2Pending,
psCommand->psSrcSync[i].ui32WriteOpsPending));
}
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_END, QUEUE_TOKEN_INSERTKM);
-
+ /* return pointer to caller to fill out private data */
*ppsCommand = psCommand;
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+ @Function : PVRSRVSubmitCommandKM
+
+ @Description :
+ updates the queue's write offset so the command can be executed.
+
+ @Input : psQueue - queue command is in
+ @Input : psCommand
+
+ @Return : PVRSRV_ERROR
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_COMMAND *psCommand)
{
-
-
-
+ /* override QAC warnings about stricter pointers */
+ /* PRQA S 3305 END_PTR_ASSIGNMENTS2 */
+ /* patch pointers in the command to be kernel pointers */
if (psCommand->ui32DstSyncCount > 0)
{
psCommand->psDstSync = (PVRSRV_SYNC_OBJECT*)(((IMG_UINTPTR_T)psQueue->pvLinQueueKM)
@@ -616,14 +845,84 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVSubmitCommandKM(PVRSRV_QUEUE_INFO *psQueue,
+ (psCommand->ui32DstSyncCount * sizeof(PVRSRV_SYNC_OBJECT))
+ (psCommand->ui32SrcSyncCount * sizeof(PVRSRV_SYNC_OBJECT)));
-
+/* PRQA L:END_PTR_ASSIGNMENTS2 */
+
+ /* update write offset before releasing access lock */
UPDATE_QUEUE_WOFF(psQueue, psCommand->uCmdSize);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function CheckIfSyncIsQueued
+ @Description Check if the specificed sync object is already queued and
+ can safely be given to the display controller.
+ This check is required as a 3rd party displayclass device can
+ have several flips "in flight" and we need to ensure that we
+ keep their pipeline full and don't deadlock waiting for them
+ to complete an operation on a surface.
+
+ @Input psSysData : system data
+ @Input psCmdData : COMMAND_COMPLETE_DATA structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+static
+PVRSRV_ERROR CheckIfSyncIsQueued(PVRSRV_SYNC_OBJECT *psSync, COMMAND_COMPLETE_DATA *psCmdData)
+{
+ IMG_UINT32 k;
+
+ if (psCmdData->bInUse)
+ {
+ for (k=0;k<psCmdData->ui32SrcSyncCount;k++)
+ {
+ if (psSync->psKernelSyncInfoKM == psCmdData->psSrcSync[k].psKernelSyncInfoKM)
+ {
+ PVRSRV_SYNC_DATA *psSyncData = psSync->psKernelSyncInfoKM->psSyncData;
+ IMG_UINT32 ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
+
+ /*
+ We still need to ensure that we don't we don't give a command
+ to the display controller if writes are outstanding on it
+ */
+ if (ui32WriteOpsComplete == psSync->ui32WriteOpsPending)
+ {
+ return PVRSRV_OK;
+ }
+ else
+ {
+ if (SYNCOPS_STALE(ui32WriteOpsComplete, psSync->ui32WriteOpsPending))
+ {
+ PVR_DPF((PVR_DBG_WARNING,
+ "CheckIfSyncIsQueued: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
+ (IMG_UINTPTR_T)psSyncData, ui32WriteOpsComplete, psSync->ui32WriteOpsPending));
+ return PVRSRV_OK;
+ }
+ }
+ }
+ }
+ }
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+}
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessCommand
+
+ @Description Tries to process a command
+
+ @Input psSysData : system data
+ @Input psCommand : PVRSRV_COMMAND structure
+ @Input bFlush : Check for stale dependencies (only used for HW recovery)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static
PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
PVRSRV_COMMAND *psCommand,
@@ -639,7 +938,7 @@ PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
DEVICE_COMMAND_DATA *psDeviceCommandData;
IMG_UINT32 ui32CCBOffset;
-
+ /* satisfy sync dependencies on the DST(s) */
psWalkerObj = psCommand->psDstSync;
psEndObj = psWalkerObj + psCommand->ui32DstSyncCount;
while (psWalkerObj < psEndObj)
@@ -647,14 +946,14 @@ PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
- ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
-
+ ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
+ /* fail if reads or writes are not up to date */
if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
- || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
{
if (!bFlush ||
!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
- !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
{
return PVRSRV_ERROR_FAILED_DEPENDENCIES;
}
@@ -663,22 +962,22 @@ PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
psWalkerObj++;
}
-
+ /* satisfy sync dependencies on the SRC(s) */
psWalkerObj = psCommand->psSrcSync;
psEndObj = psWalkerObj + psCommand->ui32SrcSyncCount;
while (psWalkerObj < psEndObj)
{
PVRSRV_SYNC_DATA *psSyncData = psWalkerObj->psKernelSyncInfoKM->psSyncData;
- ui32ReadOpsComplete = psSyncData->ui32ReadOpsComplete;
+ ui32ReadOpsComplete = psSyncData->ui32ReadOps2Complete;
ui32WriteOpsComplete = psSyncData->ui32WriteOpsComplete;
-
+ /* fail if writes are not up to date */
if ((ui32WriteOpsComplete != psWalkerObj->ui32WriteOpsPending)
- || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOpsPending))
+ || (ui32ReadOpsComplete != psWalkerObj->ui32ReadOps2Pending))
{
if (!bFlush &&
SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) &&
- SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
{
PVR_DPF((PVR_DBG_WARNING,
"PVRSRVProcessCommand: Stale syncops psSyncData:0x%x ui32WriteOpsComplete:0x%x ui32WriteOpsPending:0x%x",
@@ -687,15 +986,30 @@ PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
if (!bFlush ||
!SYNCOPS_STALE(ui32WriteOpsComplete, psWalkerObj->ui32WriteOpsPending) ||
- !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOpsPending))
+ !SYNCOPS_STALE(ui32ReadOpsComplete, psWalkerObj->ui32ReadOps2Pending))
{
- return PVRSRV_ERROR_FAILED_DEPENDENCIES;
+ IMG_UINT32 j;
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFound = IMG_FALSE;
+
+ psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
+ for (j=0;j<DC_NUM_COMMANDS_PER_TYPE;j++)
+ {
+ eError = CheckIfSyncIsQueued(psWalkerObj, psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[j]);
+
+ if (eError == PVRSRV_OK)
+ {
+ bFound = IMG_TRUE;
+ }
+ }
+ if (!bFound)
+ return PVRSRV_ERROR_FAILED_DEPENDENCIES;
}
}
psWalkerObj++;
}
-
+ /* validate device type */
if (psCommand->ui32DevIndex >= SYS_DEVICE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -704,70 +1018,74 @@ PVRSRV_ERROR PVRSRVProcessCommand(SYS_DATA *psSysData,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* fish out the appropriate storage structure for the duration of the command */
psDeviceCommandData = psSysData->apsDeviceCommandData[psCommand->ui32DevIndex];
ui32CCBOffset = psDeviceCommandData[psCommand->CommandType].ui32CCBOffset;
psCmdCompleteData = psDeviceCommandData[psCommand->CommandType].apsCmdCompleteData[ui32CCBOffset];
if (psCmdCompleteData->bInUse)
{
-
+ /* can use this to protect against concurrent execution of same command */
return PVRSRV_ERROR_FAILED_DEPENDENCIES;
}
-
+ /* mark the structure as in use */
psCmdCompleteData->bInUse = IMG_TRUE;
-
+ /* copy src updates over */
psCmdCompleteData->ui32DstSyncCount = psCommand->ui32DstSyncCount;
for (i=0; i<psCommand->ui32DstSyncCount; i++)
{
psCmdCompleteData->psDstSync[i] = psCommand->psDstSync[i];
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
- i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psDstSync[i].ui32WriteOpsPending,
ui32CCBOffset));
}
+ psCmdCompleteData->pfnCommandComplete = psCommand->pfnCommandComplete;
+ psCmdCompleteData->hCallbackData = psCommand->hCallbackData;
-
+ /* copy dst updates over */
psCmdCompleteData->ui32SrcSyncCount = psCommand->ui32SrcSyncCount;
for (i=0; i<psCommand->ui32SrcSyncCount; i++)
{
psCmdCompleteData->psSrcSync[i] = psCommand->psSrcSync[i];
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVProcessCommand: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x (CCB:%u)",
- i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending,
ui32CCBOffset));
}
-
-
-
-
-
-
-
-
-
-
+ /*
+ call the cmd specific handler:
+ it should:
+ - check the cmd specific dependencies
+ - setup private cmd complete structure
+ - execute cmd on HW
+ - store psCmdCompleteData `cookie' and later pass as
+ argument to Generic Command Complete Callback
+
+ n.b. ui32DataSize (packet size) is useful for packet validation
+ */
if (psDeviceCommandData[psCommand->CommandType].pfnCmdProc((IMG_HANDLE)psCmdCompleteData,
(IMG_UINT32)psCommand->uDataSize,
psCommand->pvData) == IMG_FALSE)
{
-
-
-
+ /*
+ clean-up:
+ free cmd complete structure
+ */
psCmdCompleteData->bInUse = IMG_FALSE;
eError = PVRSRV_ERROR_CMD_NOT_PROCESSED;
}
-
+ /* Increment the CCB offset */
psDeviceCommandData[psCommand->CommandType].ui32CCBOffset = (ui32CCBOffset + 1) % DC_NUM_COMMANDS_PER_TYPE;
return eError;
@@ -783,19 +1101,37 @@ static IMG_VOID PVRSRVProcessQueues_ForEachCb(PVRSRV_DEVICE_NODE *psDeviceNode)
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVProcessQueues
+
+ @Description Tries to process a command from each Q
+
+ @input ui32CallerID - used to distinguish between async ISR/DPC type calls
+ the synchronous services driver
+ @input bFlush - flush commands with stale dependencies (only used for HW recovery)
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
+
IMG_EXPORT
PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
{
PVRSRV_QUEUE_INFO *psQueue;
SYS_DATA *psSysData;
PVRSRV_COMMAND *psCommand;
- SysAcquireData(&psSysData);
+/* PVRSRV_DEVICE_NODE *psDeviceNode;*/
-
+ SysAcquireData(&psSysData);
+ /* Ensure we don't corrupt queue list, by blocking access. This is required for OSs where
+ multiple ISR threads may exist simultaneously (eg WinXP DPC routines)
+ */
while (OSLockResource(&psSysData->sQProcessResource, ISR_ID) != PVRSRV_OK)
{
- OSSleepms(1);
+ OSWaitus(1);
};
psQueue = psSysData->psQueueList;
@@ -818,7 +1154,7 @@ PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
if (PVRSRVProcessCommand(psSysData, psCommand, bFlush) == PVRSRV_OK)
{
-
+ /* processed cmd so update queue */
UPDATE_QUEUE_ROFF(psQueue, psCommand->uCmdSize)
continue;
}
@@ -833,7 +1169,7 @@ PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
PVRSRVSetDCState(DC_STATE_NO_FLUSH_COMMANDS);
}
-
+ /* Re-process command complete handlers if necessary. */
List_PVRSRV_DEVICE_NODE_ForEach(psSysData->psDeviceNodeList,
&PVRSRVProcessQueues_ForEachCb);
@@ -843,6 +1179,19 @@ PVRSRV_ERROR PVRSRVProcessQueues(IMG_BOOL bFlush)
}
#if defined(SUPPORT_CUSTOM_SWAP_OPERATIONS)
+/*!
+******************************************************************************
+
+ @Function PVRSRVCommandCompleteKM
+
+ @Description Updates non-private command complete sync objects
+
+ @Input hCmdCookie : command cookie
+ @Input bScheduleMISR : obsolete parameter
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_INTERNAL
IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
IMG_BOOL bScheduleMISR)
@@ -850,23 +1199,36 @@ IMG_VOID PVRSRVFreeCommandCompletePacketKM(IMG_HANDLE hCmdCookie,
COMMAND_COMPLETE_DATA *psCmdCompleteData = (COMMAND_COMPLETE_DATA *)hCmdCookie;
SYS_DATA *psSysData;
+ PVR_UNREFERENCED_PARAMETER(bScheduleMISR);
+
SysAcquireData(&psSysData);
-
+ /* free command complete storage */
psCmdCompleteData->bInUse = IMG_FALSE;
-
+ /* FIXME: This may cause unrelated devices to be woken up. */
PVRSRVScheduleDeviceCallbacks();
- if(bScheduleMISR)
- {
- OSScheduleMISR(psSysData);
- }
+ /* the MISR is always scheduled, regardless of bScheduleMISR */
+ OSScheduleMISR(psSysData);
}
-#endif
+#endif /* (SUPPORT_CUSTOM_SWAP_OPERATIONS) */
+
+
+/*!
+******************************************************************************
+
+ @Function PVRSRVCommandCompleteKM
+
+ @Description Updates non-private command complete sync objects
+ @Input hCmdCookie : command cookie
+ @Input bScheduleMISR : boolean to schedule MISR
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
IMG_BOOL bScheduleMISR)
@@ -880,45 +1242,54 @@ IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_START,
QUEUE_TOKEN_COMMAND_COMPLETE);
-
+ /* update DST(s) syncs */
for (i=0; i<psCmdCompleteData->ui32DstSyncCount; i++)
{
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->psSyncData->ui32WriteOpsComplete++;
+ PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM, IMG_NULL);
+
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_DST,
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM,
PVRSRV_SYNCOP_COMPLETE);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Dst %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psDstSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psDstSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psDstSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psDstSync[i].ui32WriteOpsPending));
}
-
+ /* update SRC(s) syncs */
for (i=0; i<psCmdCompleteData->ui32SrcSyncCount; i++)
{
- psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOpsComplete++;
+ psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->psSyncData->ui32ReadOps2Complete++;
+
+ PVRSRVKernelSyncInfoDecRef(psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM, IMG_NULL);
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_QUEUE, QUEUE_TOKEN_UPDATE_SRC,
psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM,
PVRSRV_SYNCOP_COMPLETE);
PVR_DPF((PVR_DBG_MESSAGE, "PVRSRVCommandCompleteKM: Src %u RO-VA:0x%x WO-VA:0x%x ROP:0x%x WOP:0x%x",
- i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOpsCompleteDevVAddr.uiAddr,
+ i, psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sReadOps2CompleteDevVAddr.uiAddr,
psCmdCompleteData->psSrcSync[i].psKernelSyncInfoKM->sWriteOpsCompleteDevVAddr.uiAddr,
- psCmdCompleteData->psSrcSync[i].ui32ReadOpsPending,
+ psCmdCompleteData->psSrcSync[i].ui32ReadOps2Pending,
psCmdCompleteData->psSrcSync[i].ui32WriteOpsPending));
}
PVR_TTRACE(PVRSRV_TRACE_GROUP_QUEUE, PVRSRV_TRACE_CLASS_CMD_COMP_END,
QUEUE_TOKEN_COMMAND_COMPLETE);
-
+ if (psCmdCompleteData->pfnCommandComplete)
+ {
+ psCmdCompleteData->pfnCommandComplete(psCmdCompleteData->hCallbackData);
+ }
+
+ /* free command complete storage */
psCmdCompleteData->bInUse = IMG_FALSE;
-
+ /* FIXME: This may cause unrelated devices to be woken up. */
PVRSRVScheduleDeviceCallbacks();
if(bScheduleMISR)
@@ -930,6 +1301,27 @@ IMG_VOID PVRSRVCommandCompleteKM(IMG_HANDLE hCmdCookie,
+/*!
+******************************************************************************
+
+ @Function PVRSRVRegisterCmdProcListKM
+
+ @Description
+
+ registers a list of private command processing functions with the Command
+ Queue Manager
+
+ @Input ui32DevIndex : device index
+
+ @Input ppfnCmdProcList : function ptr table of private command processors
+
+ @Input ui32MaxSyncsPerCmd : max number of syncobjects used by command
+
+ @Input ui32CmdCount : number of entries in function ptr table
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
PFN_CMD_PROC *ppfnCmdProcList,
@@ -943,7 +1335,7 @@ PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
DEVICE_COMMAND_DATA *psDeviceCommandData;
COMMAND_COMPLETE_DATA *psCmdCompleteData;
-
+ /* validate device type */
if(ui32DevIndex >= SYS_DEVICE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -952,10 +1344,10 @@ PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* acquire system data structure */
SysAcquireData(&psSysData);
-
+ /* array of pointers for each command store */
ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
ui32AllocSize,
@@ -973,15 +1365,17 @@ PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
{
psDeviceCommandData[ui32CmdTypeCounter].pfnCmdProc = ppfnCmdProcList[ui32CmdTypeCounter];
psDeviceCommandData[ui32CmdTypeCounter].ui32CCBOffset = 0;
-
+ psDeviceCommandData[ui32CmdTypeCounter].ui32MaxDstSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0];
+ psDeviceCommandData[ui32CmdTypeCounter].ui32MaxSrcSyncCount = ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1];
for (ui32CmdCounter = 0; ui32CmdCounter < DC_NUM_COMMANDS_PER_TYPE; ui32CmdCounter++)
{
-
-
- ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA)
+ /*
+ allocate storage for the sync update on command complete
+ */
+ ui32AllocSize = sizeof(COMMAND_COMPLETE_DATA) /* space for one GENERIC_CMD_COMPLETE */
+ ((ui32MaxSyncsPerCmd[ui32CmdTypeCounter][0]
+ ui32MaxSyncsPerCmd[ui32CmdTypeCounter][1])
- * sizeof(PVRSRV_SYNC_OBJECT));
+ * sizeof(PVRSRV_SYNC_OBJECT)); /* space for max sync objects */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
ui32AllocSize,
@@ -996,10 +1390,10 @@ PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = psCmdCompleteData;
-
+ /* clear memory */
OSMemSet(psCmdCompleteData, 0x00, ui32AllocSize);
-
+ /* setup sync pointers */
psCmdCompleteData->psDstSync = (PVRSRV_SYNC_OBJECT*)
(((IMG_UINTPTR_T)psCmdCompleteData)
+ sizeof(COMMAND_COMPLETE_DATA));
@@ -1015,7 +1409,7 @@ PVRSRV_ERROR PVRSRVRegisterCmdProcListKM(IMG_UINT32 ui32DevIndex,
ErrorExit:
-
+ /* clean-up if things went wrong */
if (PVRSRVRemoveCmdProcListKM(ui32DevIndex, ui32CmdCount) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -1027,6 +1421,23 @@ ErrorExit:
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRemoveCmdProcListKM
+
+ @Description
+
+ removes a list of private command processing functions and data from the
+ Queue Manager
+
+ @Input ui32DevIndex : device index
+
+ @Input ui32CmdCount : number of entries in function ptr table
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
IMG_UINT32 ui32CmdCount)
@@ -1037,7 +1448,7 @@ PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
COMMAND_COMPLETE_DATA *psCmdCompleteData;
IMG_SIZE_T ui32AllocSize;
-
+ /* validate device type */
if(ui32DevIndex >= SYS_DEVICE_COUNT)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -1046,7 +1457,7 @@ PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* acquire system data structure */
SysAcquireData(&psSysData);
psDeviceCommandData = psSysData->apsDeviceCommandData[ui32DevIndex];
@@ -1058,9 +1469,10 @@ PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
{
psCmdCompleteData = psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter];
-
+ /* free the cmd complete structure array entries */
if (psCmdCompleteData != IMG_NULL)
{
+ PVR_ASSERT(psCmdCompleteData->bInUse == IMG_FALSE);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, psCmdCompleteData->ui32AllocSize,
psCmdCompleteData, IMG_NULL);
psDeviceCommandData[ui32CmdTypeCounter].apsCmdCompleteData[ui32CmdCounter] = IMG_NULL;
@@ -1068,7 +1480,7 @@ PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
}
}
-
+ /* free the cmd complete structure array for the device */
ui32AllocSize = ui32CmdCount * sizeof(*psDeviceCommandData);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, ui32AllocSize, psDeviceCommandData, IMG_NULL);
psSysData->apsDeviceCommandData[ui32DevIndex] = IMG_NULL;
@@ -1077,3 +1489,6 @@ PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
return PVRSRV_OK;
}
+/******************************************************************************
+ End of file (queue.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/common/ra.c b/sgx/services4/srvkm/common/ra.c
index e93f05f..819c36a 100644
--- a/sgx/services4/srvkm/common/ra.c
+++ b/sgx/services4/srvkm/common/ra.c
@@ -1,28 +1,90 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Allocator
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+@Description
+ Implements generic resource allocation. The resource
+ allocator was originally intended to manage address spaces in
+ practice the resource allocator is generic and can manages arbitrary
+ sets of integers.
+
+ Resources are allocated from arenas. Arena's can be created with an
+ initial span of resources. Further resources spans can be added to
+ arenas. A call back mechanism allows an arena to request further
+ resource spans on demand.
+
+ Each arena maintains an ordered list of resource segments each
+ described by a boundary tag. Each boundary tag describes a segment
+ of resources which are either 'free', available for allocation, or
+ 'busy' currently allocated. Adjacent 'free' segments are always
+ coallesced to avoid fragmentation.
+
+ For allocation, all 'free' segments are kept on lists of 'free'
+ segments in a table index by pvr_log2(segment size). ie Each table index
+ n holds 'free' segments in the size range 2**(n-1) -> 2**n.
+
+ Allocation policy is based on an *almost* best fit
+ stratedy. Choosing any segment from the appropriate table entry
+ guarantees that we choose a segment which is with a power of 2 of
+ the size we are allocating.
+
+ Allocated segments are inserted into a self scaling hash table which
+ maps the base resource of the span to the relevant boundary
+ tag. This allows the code to get back to the bounary tag without
+ exporting explicit boundary tag references through the API.
+
+ Each arena has an associated quantum size, all allocations from the
+ arena are made in multiples of the basic quantum.
+
+ On resource exhaustion in an arena, a callback if provided will be
+ used to request further resources. Resouces spans allocated by the
+ callback mechanism are delimited by special boundary tag markers of
+ zero span, 'span' markers. Span markers are never coallesced. Span
+ markers are used to detect when an imported span is completely free
+ and can be deallocated by the callback mechanism.
+*/ /**************************************************************************/
+
+/* Issues:
+ * - flags, flags are passed into the resource allocator but are not currently used.
+ * - determination, of import size, is currently braindead.
+ * - debug code should be moved out to own module and #ifdef'd
+ */
#include "services_headers.h"
#include "hash.h"
@@ -30,7 +92,7 @@
#include "buffer_manager.h"
#include "osfunc.h"
-#ifdef __linux__
+#if defined(__linux__) && defined(__KERNEL__)
#include <linux/kernel.h>
#include "proc.h"
#endif
@@ -39,10 +101,18 @@
#include <stdio.h>
#endif
+/* The initial, and minimum size of the live address -> boundary tag
+ structure hash table. The value 64 is a fairly arbitrary
+ choice. The hash table resizes on demand so the value choosen is
+ not critical. */
#define MINIMUM_HASH_SIZE (64)
#if defined(VALIDATE_ARENA_TEST)
+/* This test validates the doubly linked ordered list of boundary tags, by
+checking that adjacent members of the list have compatible eResourceSpan
+and eResourceType values. */
+
typedef enum RESOURCE_DESCRIPTOR_TAG {
RESOURCE_SPAN_LIVE = 10,
@@ -67,33 +137,36 @@ static IMG_UINT32 ui32BoundaryTagID = 0;
IMG_UINT32 ValidateArena(RA_ARENA *pArena);
#endif
+/* boundary tags, used to describe a resource segment */
struct _BT_
{
enum bt_type
{
- btt_span,
- btt_free,
- btt_live
+ btt_span, /* span markers */
+ btt_free, /* free resource segment */
+ btt_live /* allocated resource segment */
} type;
-
+ /* The base resource and extent of this segment */
IMG_UINTPTR_T base;
IMG_SIZE_T uSize;
-
+ /* doubly linked ordered list of all segments within the arena */
struct _BT_ *pNextSegment;
struct _BT_ *pPrevSegment;
-
+ /* doubly linked un-ordered list of free segments. */
struct _BT_ *pNextFree;
struct _BT_ *pPrevFree;
-
+ /* a user reference associated with this span, user references are
+ * currently only provided in the callback mechanism */
BM_MAPPING *psMapping;
#if defined(VALIDATE_ARENA_TEST)
RESOURCE_DESCRIPTOR eResourceSpan;
RESOURCE_TYPE eResourceType;
-
+ /* This variable provides a reference (used in debug messages) to incompatible
+ boundary tags within the doubly linked ordered list. */
IMG_UINT32 ui32BoundaryTagID;
#endif
@@ -101,40 +174,45 @@ struct _BT_
typedef struct _BT_ BT;
+/* resource allocation arena */
struct _RA_ARENA_
{
-
+ /* arena name for diagnostics output */
IMG_CHAR *name;
-
+ /* allocations within this arena are quantum sized */
IMG_SIZE_T uQuantum;
-
+ /* import interface, if provided */
IMG_BOOL (*pImportAlloc)(IMG_VOID *,
IMG_SIZE_T uSize,
IMG_SIZE_T *pActualSize,
BM_MAPPING **ppsMapping,
IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase);
IMG_VOID (*pImportFree) (IMG_VOID *,
IMG_UINTPTR_T,
BM_MAPPING *psMapping);
IMG_VOID (*pBackingStoreFree) (IMG_VOID *, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE);
-
+ /* arbitrary handle provided by arena owner to be passed into the
+ * import alloc and free hooks */
IMG_VOID *pImportHandle;
-
+ /* head of list of free boundary tags for indexed by pvr_log2 of the
+ boundary tag size */
#define FREE_TABLE_LIMIT 32
-
+ /* power-of-two table of free lists */
BT *aHeadFree [FREE_TABLE_LIMIT];
-
+ /* resource ordered segment list */
BT *pHeadSegment;
BT *pTailSegment;
-
+ /* segment address to boundary tag hash table */
HASH_TABLE *pSegmentHash;
#ifdef RA_STATS
@@ -150,6 +228,7 @@ struct _RA_ARENA_
IMG_BOOL bInitProcEntry;
#endif
};
+/* #define ENABLE_RA_DUMP 1 */
#if defined(ENABLE_RA_DUMP)
IMG_VOID RA_Dump (RA_ARENA *pArena);
#endif
@@ -162,7 +241,7 @@ static void* RA_ProcSeqOff2ElementInfo(struct seq_file * sfile, loff_t off);
static void RA_ProcSeqShowRegs(struct seq_file *sfile, void* el);
static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off);
-#endif
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
#ifdef USE_BM_FREESPACE_CHECK
IMG_VOID CheckBMFreespace(IMG_VOID);
@@ -185,12 +264,33 @@ static IMG_CHAR *ReplaceSpaces(IMG_CHAR * const pS)
}
#endif
+/*!
+******************************************************************************
+ @Function _RequestAllocFail
+
+ @Description Default callback allocator used if no callback is
+ specified, always fails to allocate further resources to the
+ arena.
+
+ @Input _h - callback handle
+ @Input _uSize - requested allocation size
+ @Output _pActualSize - actual allocation size
+ @Input _pRef - user reference
+ @Input _uflags - allocation flags
+ @Input _pvPrivData - private data
+ @Input _ui32PrivDataLength - private data length
+ @Input _pBase - receives allocated base
+
+ @Return IMG_FALSE, this function always fails to allocate.
+******************************************************************************/
static IMG_BOOL
_RequestAllocFail (IMG_VOID *_h,
IMG_SIZE_T _uSize,
IMG_SIZE_T *_pActualSize,
BM_MAPPING **_ppsMapping,
IMG_UINT32 _uFlags,
+ IMG_PVOID _pvPrivData,
+ IMG_UINT32 _ui32PrivDataLength,
IMG_UINTPTR_T *_pBase)
{
PVR_UNREFERENCED_PARAMETER (_h);
@@ -199,10 +299,22 @@ _RequestAllocFail (IMG_VOID *_h,
PVR_UNREFERENCED_PARAMETER (_ppsMapping);
PVR_UNREFERENCED_PARAMETER (_uFlags);
PVR_UNREFERENCED_PARAMETER (_pBase);
+ PVR_UNREFERENCED_PARAMETER (_pvPrivData);
+ PVR_UNREFERENCED_PARAMETER (_ui32PrivDataLength);
return IMG_FALSE;
}
+/*!
+******************************************************************************
+ @Function pvr_log2
+
+ @Description Computes the floor of the log base 2 of a unsigned integer
+
+ @Input n - unsigned integer
+
+ @Return Floor(Log2(n))
+******************************************************************************/
static IMG_UINT32
pvr_log2 (IMG_SIZE_T n)
{
@@ -216,6 +328,19 @@ pvr_log2 (IMG_SIZE_T n)
return l;
}
+/*!
+******************************************************************************
+ @Function _SegmentListInsertAfter
+
+ @Description Insert a boundary tag into an arena segment list after a
+ specified boundary tag.
+
+ @Input pArena - the arena.
+ @Input pInsertionPoint - the insertion point.
+ @Input pBT - the boundary tag to insert.
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
static PVRSRV_ERROR
_SegmentListInsertAfter (RA_ARENA *pArena,
BT *pInsertionPoint,
@@ -241,12 +366,24 @@ _SegmentListInsertAfter (RA_ARENA *pArena,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function _SegmentListInsert
+
+ @Description Insert a boundary tag into an arena segment list at the
+ appropriate point.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to insert.
+
+ @Return None
+******************************************************************************/
static PVRSRV_ERROR
_SegmentListInsert (RA_ARENA *pArena, BT *pBT)
{
PVRSRV_ERROR eError = PVRSRV_OK;
-
+ /* insert into the segment chain */
if (pArena->pHeadSegment == IMG_NULL)
{
pArena->pHeadSegment = pArena->pTailSegment = pBT;
@@ -258,7 +395,8 @@ _SegmentListInsert (RA_ARENA *pArena, BT *pBT)
if (pBT->base < pArena->pHeadSegment->base)
{
-
+ /* The base address of pBT is less than the base address of the boundary tag
+ at the head of the list - so insert this boundary tag at the head. */
pBT->pNextSegment = pArena->pHeadSegment;
pArena->pHeadSegment->pPrevSegment = pBT;
pArena->pHeadSegment = pBT;
@@ -267,9 +405,10 @@ _SegmentListInsert (RA_ARENA *pArena, BT *pBT)
else
{
-
-
-
+ /* The base address of pBT is greater than or equal to that of the boundary tag
+ at the head of the list. Search for the insertion point: pBT must be inserted
+ before the first boundary tag with a greater base value - or at the end of the list.
+ */
pBTScan = pArena->pHeadSegment;
while ((pBTScan->pNextSegment != IMG_NULL) && (pBT->base >= pBTScan->pNextSegment->base))
@@ -287,6 +426,17 @@ _SegmentListInsert (RA_ARENA *pArena, BT *pBT)
return eError;
}
+/*!
+******************************************************************************
+ @Function _SegmentListRemove
+
+ @Description Remove a boundary tag from an arena segment list.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to remove.
+
+ @Return None
+******************************************************************************/
static IMG_VOID
_SegmentListRemove (RA_ARENA *pArena, BT *pBT)
{
@@ -301,6 +451,23 @@ _SegmentListRemove (RA_ARENA *pArena, BT *pBT)
pBT->pNextSegment->pPrevSegment = pBT->pPrevSegment;
}
+/*!
+******************************************************************************
+ @Function _SegmentSplit
+
+ @Description Split a segment into two, maintain the arena segment list. The
+ boundary tag should not be in the free table. Neither the
+ original or the new neighbour bounary tag will be in the free
+ table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to split.
+ @Input uSize - the required segment size of boundary tag after
+ splitting.
+
+ @Return New neighbour boundary tag.
+
+******************************************************************************/
static BT *
_SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
{
@@ -363,6 +530,18 @@ _SegmentSplit (RA_ARENA *pArena, BT *pBT, IMG_SIZE_T uSize)
return pNeighbour;
}
+/*!
+******************************************************************************
+ @Function _FreeListInsert
+
+ @Description Insert a boundary tag into an arena free table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag.
+
+ @Return None
+
+******************************************************************************/
static IMG_VOID
_FreeListInsert (RA_ARENA *pArena, BT *pBT)
{
@@ -376,6 +555,18 @@ _FreeListInsert (RA_ARENA *pArena, BT *pBT)
pArena->aHeadFree [uIndex] = pBT;
}
+/*!
+******************************************************************************
+ @Function _FreeListRemove
+
+ @Description Remove a boundary tag from an arena free table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag.
+
+ @Return None
+
+******************************************************************************/
static IMG_VOID
_FreeListRemove (RA_ARENA *pArena, BT *pBT)
{
@@ -389,6 +580,18 @@ _FreeListRemove (RA_ARENA *pArena, BT *pBT)
pBT->pPrevFree->pNextFree = pBT->pNextFree;
}
+/*!
+******************************************************************************
+ @Function _BuildSpanMarker
+
+ @Description Construct a span marker boundary tag.
+
+ @Input pArena - arena to contain span marker
+ @Input base - the base of the bounary tag.
+
+ @Return span marker boundary tag
+
+******************************************************************************/
static BT *
_BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
@@ -416,6 +619,18 @@ _BuildSpanMarker (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
return pBT;
}
+/*!
+******************************************************************************
+ @Function _BuildBT
+
+ @Description Construct a boundary tag for a free segment.
+
+ @Input base - the base of the resource segment.
+ @Input uSize - the extent of the resouce segment.
+
+ @Return boundary tag
+
+******************************************************************************/
static BT *
_BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
@@ -442,6 +657,20 @@ _BuildBT (IMG_UINTPTR_T base, IMG_SIZE_T uSize)
return pBT;
}
+/*!
+******************************************************************************
+ @Function _InsertResource
+
+ @Description Add a free resource segment to an arena.
+
+ @Input pArena - the arena.
+ @Input base - the base of the resource segment.
+ @Input uSize - the extent of the resource segment.
+
+ @Return New bucket pointer
+ IMG_NULL failure
+
+******************************************************************************/
static BT *
_InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
@@ -477,6 +706,19 @@ _InsertResource (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
return pBT;
}
+/*!
+******************************************************************************
+ @Function _InsertResourceSpan
+
+ @Description Add a free resource span to an arena, complete with span markers.
+
+ @Input pArena - the arena.
+ @Input base - the base of the resource segment.
+ @Input uSize - the extent of the resource segment.
+
+ @Return the boundary tag representing the free resource segment,
+ or IMG_NULL on failure.
+******************************************************************************/
static BT *
_InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
@@ -551,22 +793,40 @@ _InsertResourceSpan (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
#ifdef RA_STATS
pArena->sStatistics.uTotalResourceCount+=uSize;
+/* pArena->sStatistics.uFreeResourceCount+=uSize;
+ This has got to be wrong as uFreeResourceCount ends
+ up larger than uTotalResourceCount by uTotalResourceCount
+ - allocated memory
+*/
#endif
return pBT;
fail_SegListInsert:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_bt:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanEnd, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_end:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pSpanStart, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
fail_start:
return IMG_NULL;
}
+/*!
+******************************************************************************
+ @Function _FreeBT
+
+ @Description Free a boundary tag taking care of the segment list and the
+ boundary tag free table.
+
+ @Input pArena - the arena.
+ @Input pBT - the boundary tag to free.
+ @Input bFreeBackingStore - Should backing for the memory be freed
+ as well.
+ @Return None
+******************************************************************************/
static IMG_VOID
_FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
{
@@ -592,7 +852,7 @@ _FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
uOrigBase = pBT->base;
uOrigSize = pBT->uSize;
-
+ /* try and coalesce with left neighbour */
pNeighbour = pBT->pPrevSegment;
if (pNeighbour!=IMG_NULL
&& pNeighbour->type == btt_free
@@ -603,13 +863,13 @@ _FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
pBT->base = pNeighbour->base;
pBT->uSize += pNeighbour->uSize;
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
#ifdef RA_STATS
pArena->sStatistics.uFreeSegmentCount--;
#endif
}
-
+ /* try to coalesce with right neighbour */
pNeighbour = pBT->pNextSegment;
if (pNeighbour!=IMG_NULL
&& pNeighbour->type == btt_free
@@ -619,28 +879,28 @@ _FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
_SegmentListRemove (pArena, pNeighbour);
pBT->uSize += pNeighbour->uSize;
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pNeighbour, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
#ifdef RA_STATS
pArena->sStatistics.uFreeSegmentCount--;
#endif
}
-
+ /* try to free backing store memory. */
if (pArena->pBackingStoreFree != IMG_NULL && bFreeBackingStore)
{
IMG_UINTPTR_T uRoundedStart, uRoundedEnd;
-
+ /* Work out the first address we might be able to free. */
uRoundedStart = (uOrigBase / pArena->uQuantum) * pArena->uQuantum;
-
+ /* If a span is still using that address then leave it. */
if (uRoundedStart < pBT->base)
{
uRoundedStart += pArena->uQuantum;
}
-
+ /* Work out the last address we might be able to free. */
uRoundedEnd = ((uOrigBase + uOrigSize + pArena->uQuantum - 1) / pArena->uQuantum) * pArena->uQuantum;
-
+ /* If a span is still using that addres then leave it. */
if (uRoundedEnd > (pBT->base + pBT->uSize))
{
uRoundedEnd -= pArena->uQuantum;
@@ -669,17 +929,35 @@ _FreeBT (RA_ARENA *pArena, BT *pBT, IMG_BOOL bFreeBackingStore)
pArena->sStatistics.uTotalResourceCount-=pBT->uSize;
#endif
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), next, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), prev, IMG_NULL);
-
+ /*not nulling original pointer, already overwritten*/
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
else
_FreeListInsert (pArena, pBT);
}
+/*!
+******************************************************************************
+ @Function _AttemptAllocAligned
+
+ @Description Attempt an allocation from an arena.
+
+ @Input pArena - the arena.
+ @Input uSize - the requested allocation size.
+ @Output ppsMapping - the user references associated with
+ the allocated segment.
+ @Input flags - allocation flags
+ @Input uAlignment - required uAlignment, or 0
+ @Input uAlignmentOffset
+ @Output base - allocated resource base
+
+ @Return IMG_FALSE failure
+ IMG_TRUE success
+******************************************************************************/
static IMG_BOOL
_AttemptAllocAligned (RA_ARENA *pArena,
IMG_SIZE_T uSize,
@@ -700,16 +978,11 @@ _AttemptAllocAligned (RA_ARENA *pArena,
if (uAlignment>1)
uAlignmentOffset %= uAlignment;
-
-
+ /* search for a near fit free boundary tag, start looking at the
+ pvr_log2 free table for our required size and work on up the
+ table. */
uIndex = pvr_log2 (uSize);
-#if 0
-
- if (1u<<uIndex < uSize)
- uIndex++;
-#endif
-
while (uIndex < FREE_TABLE_LIMIT && pArena->aHeadFree[uIndex]==IMG_NULL)
uIndex++;
@@ -717,7 +990,7 @@ _AttemptAllocAligned (RA_ARENA *pArena,
{
if (pArena->aHeadFree[uIndex]!=IMG_NULL)
{
-
+ /* we have a cached free boundary tag */
BT *pBT;
pBT = pArena->aHeadFree [uIndex];
@@ -748,16 +1021,16 @@ _AttemptAllocAligned (RA_ARENA *pArena,
pArena->sStatistics.uFreeResourceCount-=pBT->uSize;
#endif
-
+ /* with uAlignment we might need to discard the front of this segment */
if (aligned_base > pBT->base)
{
BT *pNeighbour;
pNeighbour = _SegmentSplit (pArena, pBT, (IMG_SIZE_T)(aligned_base - pBT->base));
-
+ /* partition the buffer, create a new boundary tag */
if (pNeighbour==IMG_NULL)
{
PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Front split failed"));
-
+ /* Put pBT back in the list */
_FreeListInsert (pArena, pBT);
return IMG_FALSE;
}
@@ -770,16 +1043,16 @@ _AttemptAllocAligned (RA_ARENA *pArena,
pBT = pNeighbour;
}
-
+ /* the segment might be too big, if so, discard the back of the segment */
if (pBT->uSize > uSize)
{
BT *pNeighbour;
pNeighbour = _SegmentSplit (pArena, pBT, uSize);
-
+ /* partition the buffer, create a new boundary tag */
if (pNeighbour==IMG_NULL)
{
PVR_DPF ((PVR_DBG_ERROR,"_AttemptAllocAligned: Back split failed"));
-
+ /* Put pBT back in the list */
_FreeListInsert (pArena, pBT);
return IMG_FALSE;
}
@@ -840,6 +1113,23 @@ _AttemptAllocAligned (RA_ARENA *pArena,
+/*!
+******************************************************************************
+ @Function RA_Create
+
+ @Description To create a resource arena.
+
+ @Input name - the name of the arena for diagnostic purposes.
+ @Input base - the base of an initial resource span or 0.
+ @Input uSize - the size of an initial resource span or 0.
+ @Input uQuantum - the arena allocation quantum.
+ @Input alloc - a resource allocation callback or 0.
+ @Input free - a resource de-allocation callback or 0.
+ @Input backingstore_free - a callback to free resources for spans or 0.
+ @Input pImportHandle - handle passed to alloc and free or 0.
+
+ @Return arena handle, or IMG_NULL.
+******************************************************************************/
RA_ARENA *
RA_Create (IMG_CHAR *name,
IMG_UINTPTR_T base,
@@ -847,7 +1137,9 @@ RA_Create (IMG_CHAR *name,
BM_MAPPING *psMapping,
IMG_SIZE_T uQuantum,
IMG_BOOL (*imp_alloc)(IMG_VOID *, IMG_SIZE_T uSize, IMG_SIZE_T *pActualSize,
- BM_MAPPING **ppsMapping, IMG_UINT32 _flags, IMG_UINTPTR_T *pBase),
+ BM_MAPPING **ppsMapping, IMG_UINT32 _flags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength,
+ IMG_UINTPTR_T *pBase),
IMG_VOID (*imp_free) (IMG_VOID *, IMG_UINTPTR_T, BM_MAPPING *),
IMG_VOID (*backingstore_free) (IMG_VOID*, IMG_SIZE_T, IMG_SIZE_T, IMG_HANDLE),
IMG_VOID *pImportHandle)
@@ -908,7 +1200,7 @@ RA_Create (IMG_CHAR *name,
pArena->bInitProcEntry = !PVRSRVGetInitServerState(PVRSRV_INIT_SERVER_SUCCESSFUL);
-
+ /* Don't put shared heap info into a per process /proc subdirectory */
pfnCreateProcEntrySeq = pArena->bInitProcEntry ? CreateProcEntrySeq : CreatePerProcessProcEntrySeq;
ret = snprintf(szProcInfoName, sizeof(szProcInfoName), "ra_info_%s", pArena->name);
@@ -935,7 +1227,7 @@ RA_Create (IMG_CHAR *name,
PVR_DPF((PVR_DBG_ERROR, "RA_Create: couldn't create ra_segs proc entry for arena %s", pArena->name));
}
}
-#endif
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
pArena->pSegmentHash = HASH_Create (MINIMUM_HASH_SIZE);
if (pArena->pSegmentHash==IMG_NULL)
@@ -959,11 +1251,22 @@ insert_fail:
HASH_Delete (pArena->pSegmentHash);
hash_fail:
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
arena_fail:
return IMG_NULL;
}
+/*!
+******************************************************************************
+ @Function RA_Delete
+
+ @Description To delete a resource arena. All resources allocated from
+ the arena must be freed before deleting the arena.
+
+ @Input pArena - the arena to delete.
+
+ @Return None
+******************************************************************************/
IMG_VOID
RA_Delete (RA_ARENA *pArena)
{
@@ -996,7 +1299,7 @@ RA_Delete (RA_ARENA *pArena)
_SegmentListRemove (pArena, pBT);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(BT), pBT, IMG_NULL);
-
+ /*not nulling original pointer, it has changed*/
#ifdef RA_STATS
pArena->sStatistics.uSpanCount--;
#endif
@@ -1020,9 +1323,20 @@ RA_Delete (RA_ARENA *pArena)
#endif
HASH_Delete (pArena->pSegmentHash);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RA_ARENA), pArena, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
+/*!
+******************************************************************************
+ @Function RA_TestDelete
+
+ @Description To test whether it is safe to delete a resource arena. If any
+ allocations have not been freed, the RA must not be deleted.
+
+ @Input pArena - the arena to test.
+
+ @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
+******************************************************************************/
IMG_BOOL
RA_TestDelete (RA_ARENA *pArena)
{
@@ -1045,6 +1359,20 @@ RA_TestDelete (RA_ARENA *pArena)
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ @Function RA_Add
+
+ @Description To add a resource span to an arena. The span must not
+ overlapp with any span previously added to the arena.
+
+ @Input pArena - the arena to add a span into.
+ @Input base - the base of the span.
+ @Input uSize - the extent of the span.
+
+ @Return IMG_TRUE - Success
+ IMG_FALSE - failure
+******************************************************************************/
IMG_BOOL
RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
{
@@ -1063,6 +1391,29 @@ RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize)
return ((IMG_BOOL)(_InsertResource (pArena, base, uSize) != IMG_NULL));
}
+/*!
+******************************************************************************
+ @Function RA_Alloc
+
+ @Description To allocate resource from an arena.
+
+ @Input pArena - the arena
+ @Input uRequestSize - the size of resource segment requested.
+ @Output pActualSize - the actual size of resource segment
+ allocated, typcially rounded up by quantum.
+ @Output ppsMapping - the user reference associated with allocated resource span.
+ @Input uFlags - flags influencing allocation policy.
+ @Input uAlignment - the uAlignment constraint required for the
+ allocated segment, use 0 if uAlignment not required.
+ @Input uAlignmentOffset
+ @Input pvPrivData - opaque private data passed through to allocator
+ @Input ui32PrivDataLength - length of opaque private data
+
+ @Output base - allocated base resource
+
+ @Return IMG_TRUE - success
+ IMG_FALSE - failure
+******************************************************************************/
IMG_BOOL
RA_Alloc (RA_ARENA *pArena,
IMG_SIZE_T uRequestSize,
@@ -1071,6 +1422,8 @@ RA_Alloc (RA_ARENA *pArena,
IMG_UINT32 uFlags,
IMG_UINT32 uAlignment,
IMG_UINT32 uAlignmentOffset,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *base)
{
IMG_BOOL bResult;
@@ -1101,8 +1454,9 @@ RA_Alloc (RA_ARENA *pArena,
"RA_Alloc: arena='%s', size=0x%x(0x%x), alignment=0x%x, offset=0x%x",
pArena->name, uSize, uRequestSize, uAlignment, uAlignmentOffset));
-
-
+ /* if allocation failed then we might have an import source which
+ can provide more resource, else we will have to fail the
+ allocation to the caller. */
bResult = _AttemptAllocAligned (pArena, uSize, ppsMapping, uFlags,
uAlignment, uAlignmentOffset, base);
if (!bResult)
@@ -1111,34 +1465,38 @@ RA_Alloc (RA_ARENA *pArena,
IMG_UINTPTR_T import_base;
IMG_SIZE_T uImportSize = uSize;
-
-
-
+ /*
+ Ensure that we allocate sufficient space to meet the uAlignment
+ constraint
+ */
if (uAlignment > pArena->uQuantum)
{
uImportSize += (uAlignment - 1);
}
-
+ /* ensure that we import according to the quanta of this arena */
uImportSize = ((uImportSize + pArena->uQuantum - 1)/pArena->uQuantum)*pArena->uQuantum;
bResult =
pArena->pImportAlloc (pArena->pImportHandle, uImportSize, &uImportSize,
- &psImportMapping, uFlags, &import_base);
+ &psImportMapping, uFlags,
+ pvPrivData, ui32PrivDataLength, &import_base);
if (bResult)
{
BT *pBT;
pBT = _InsertResourceSpan (pArena, import_base, uImportSize);
-
+ /* successfully import more resource, create a span to
+ represent it and retry the allocation attempt */
if (pBT == IMG_NULL)
{
-
+ /* insufficient resources to insert the newly acquired span,
+ so free it back again */
pArena->pImportFree(pArena->pImportHandle, import_base,
psImportMapping);
PVR_DPF ((PVR_DBG_MESSAGE,
"RA_Alloc: name='%s', size=0x%x failed!",
pArena->name, uSize));
-
+ /* RA_Dump (arena); */
return IMG_FALSE;
}
pBT->psMapping = psImportMapping;
@@ -1168,7 +1526,9 @@ RA_Alloc (RA_ARENA *pArena,
"RA_Alloc: name='%s', size=0x%x, *base=0x%x = %d",
pArena->name, uSize, *base, bResult));
-
+ /* RA_Dump (pArena);
+ ra_stats (pArena);
+ */
#if defined(VALIDATE_ARENA_TEST)
ValidateArena(pArena);
@@ -1180,6 +1540,20 @@ RA_Alloc (RA_ARENA *pArena,
#if defined(VALIDATE_ARENA_TEST)
+/*!
+******************************************************************************
+ @Function ValidateArena
+
+ @Description Validate an arena by checking that adjacent members of the
+ double linked ordered list are compatible. PVR_DBG_BREAK and
+ PVR_DPF messages are used when an error is detected.
+ NOTE: A DEBUG build is required for PVR_DBG_BREAK and PVR_DPF
+ to operate.
+
+ @Input pArena - the arena
+
+ @Return 0
+******************************************************************************/
IMG_UINT32 ValidateArena(RA_ARENA *pArena)
{
BT* pSegment;
@@ -1208,7 +1582,7 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
{
-
+ /* error - next span must be live, free or end */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
@@ -1221,7 +1595,7 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_END)))
{
-
+ /* error - next span must be live or end */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
@@ -1235,7 +1609,7 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_END))
{
-
+ /* error - next span cannot be live, free or end */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
@@ -1249,7 +1623,7 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
if (!((eNextSpan == IMPORTED_RESOURCE_SPAN_LIVE) ||
(eNextSpan == IMPORTED_RESOURCE_SPAN_FREE)))
{
-
+ /* error - next span must be live or free */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
@@ -1282,7 +1656,7 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
(eNextSpan == RESOURCE_SPAN_LIVE)))
{
-
+ /* error - next span must be free or live */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
@@ -1295,7 +1669,7 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
if (!((eNextSpan == RESOURCE_SPAN_FREE) ||
(eNextSpan == RESOURCE_SPAN_LIVE)))
{
-
+ /* error - next span must be free or live */
PVR_DPF((PVR_DBG_ERROR, "ValidateArena ERROR: adjacent boundary tags %d (base=0x%x) and %d (base=0x%x) are incompatible (arena: %s)",
pSegment->ui32BoundaryTagID, pSegment->base, pSegment->pNextSegment->ui32BoundaryTagID, pSegment->pNextSegment->base, pArena->name));
@@ -1327,6 +1701,18 @@ IMG_UINT32 ValidateArena(RA_ARENA *pArena)
#endif
+/*!
+******************************************************************************
+ @Function RA_Free
+
+ @Description To free a resource segment.
+
+ @Input pArena - the arena the segment was originally allocated from.
+ @Input base - the base of the resource span to free.
+ @Input bFreeBackingStore - Should backing store memory be freed.
+
+ @Return None
+******************************************************************************/
IMG_VOID
RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
{
@@ -1386,6 +1772,17 @@ RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore)
}
+/*!
+******************************************************************************
+ @Function RA_GetNextLiveSegment
+
+ @Description Returns details of the next live resource segments
+
+ @Input pArena - the arena the segment was originally allocated from.
+ @InOut psSegDetails - rtn details of segments
+
+ @Return IMG_TRUE if operation succeeded
+******************************************************************************/
IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails)
{
BT *pBT;
@@ -1400,7 +1797,7 @@ IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetai
pBT = pArena->pHeadSegment;
}
-
+ /* walk the arena segments and write live one to the buffer */
while (pBT != IMG_NULL)
{
if (pBT->type == btt_live)
@@ -1479,9 +1876,19 @@ _BTType (IMG_INT eType)
}
return "junk";
}
-#endif
+#endif /*defined(CONFIG_PROC_FS) && defined(DEBUG)*/
#if defined(ENABLE_RA_DUMP)
+/*!
+******************************************************************************
+ @Function RA_Dump
+
+ @Description To dump a readable description of an arena. Diagnostic only.
+
+ @Input pArena - the arena to dump.
+
+ @Return None
+******************************************************************************/
IMG_VOID
RA_Dump (RA_ARENA *pArena)
{
@@ -1501,16 +1908,15 @@ RA_Dump (RA_ARENA *pArena)
for (pBT=pArena->pHeadSegment; pBT!=IMG_NULL; pBT=pBT->pNextSegment)
{
- PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s ref=%08X",
- (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type),
- pBT->pRef));
+ PVR_DPF ((PVR_DBG_MESSAGE,"\tbase=0x%x size=0x%x type=%s",
+ (IMG_UINT32) pBT->base, pBT->uSize, _BTType (pBT->type)));
}
#ifdef HASH_TRACE
HASH_Dump (pArena->pSegmentHash);
#endif
}
-#endif
+#endif /* #if defined(ENABLE_RA_DUMP) */
#if defined(CONFIG_PROC_FS) && defined(DEBUG)
@@ -1607,10 +2013,22 @@ static void* RA_ProcSeqOff2ElementRegs(struct seq_file * sfile, loff_t off)
return (void*)pBT;
}
-#endif
+#endif /* defined(CONFIG_PROC_FS) && defined(DEBUG) */
#ifdef RA_STATS
+/*!
+******************************************************************************
+ @Function RA_GetStats
+
+ @Description Gets the arena stats and places in client buffer
+
+ @Input pArena - the arena to print statistics for.
+ @Input ppszStr - caller string to fill
+ @Input pui32StrLen - length of caller string
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
IMG_CHAR **ppszStr,
IMG_UINT32 *pui32StrLen)
@@ -1723,3 +2141,10 @@ PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
}
#endif
+/******************************************************************************
+ End of file (ra.c)
+******************************************************************************/
+
+
+
+
diff --git a/sgx/services4/srvkm/common/refcount.c b/sgx/services4/srvkm/common/refcount.c
new file mode 100644
index 0000000..480428a
--- /dev/null
+++ b/sgx/services4/srvkm/common/refcount.c
@@ -0,0 +1,584 @@
+/*************************************************************************/ /*!
+@Title Services reference count debugging
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+#include "services_headers.h"
+
+#ifndef __linux__
+#warning Reference count debugging is not thread-safe on this platform
+#define PVRSRV_LOCK_CCB()
+#define PVRSRV_UNLOCK_CCB()
+#else /* __linux__ */
+#include <linux/mutex.h>
+static DEFINE_MUTEX(gsCCBLock);
+#define PVRSRV_LOCK_CCB() mutex_lock(&gsCCBLock)
+#define PVRSRV_UNLOCK_CCB() mutex_unlock(&gsCCBLock)
+#endif /* __linux__ */
+
+#define PVRSRV_REFCOUNT_CCB_MAX 512
+#define PVRSRV_REFCOUNT_CCB_MESG_MAX 80
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO (1U << 0)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO (1U << 1)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF (1U << 2)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2 (1U << 3)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC (1U << 4)
+
+#if defined(__linux__)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP (1U << 16)
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 (1U << 17)
+#else
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP 0
+#define PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2 0
+#endif
+
+#define PVRSRV_REFCOUNT_CCB_DEBUG_ALL ~0U
+
+/*static const IMG_UINT guiDebugMask = PVRSRV_REFCOUNT_CCB_DEBUG_ALL;*/
+static const IMG_UINT guiDebugMask =
+ PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO |
+ PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2;
+
+typedef struct
+{
+ const IMG_CHAR *pszFile;
+ IMG_INT iLine;
+ IMG_UINT32 ui32PID;
+ IMG_CHAR pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX];
+}
+PVRSRV_REFCOUNT_CCB;
+
+static PVRSRV_REFCOUNT_CCB gsRefCountCCB[PVRSRV_REFCOUNT_CCB_MAX];
+static IMG_UINT giOffset;
+
+static const IMG_CHAR gszHeader[] =
+ /* 10 20 30 40 50 60 70
+ * 345678901234567890123456789012345678901234567890123456789012345678901
+ */
+ "TYPE SYNCINFO MEMINFO MEMHANDLE OTHER REF REF' SIZE PID";
+ /* NCINFO deadbeef deadbeef deadbeef deadbeef 1234 1234 deadbeef */
+
+#define PVRSRV_REFCOUNT_CCB_FMT_STRING "%8.8s %8p %8p %8p %8p %.4d %.4d %.8x"
+
+IMG_INTERNAL
+void PVRSRVDumpRefCountCCB(void)
+{
+ int i;
+
+ PVRSRV_LOCK_CCB();
+
+ PVR_LOG(("%s", gszHeader));
+
+ for(i = 0; i < PVRSRV_REFCOUNT_CCB_MAX; i++)
+ {
+ PVRSRV_REFCOUNT_CCB *psRefCountCCBEntry =
+ &gsRefCountCCB[(giOffset + i) % PVRSRV_REFCOUNT_CCB_MAX];
+
+ /* Early on, we won't have MAX_REFCOUNT_CCB_SIZE messages */
+ if(!psRefCountCCBEntry->pszFile)
+ break;
+
+ PVR_LOG(("%s %d %s:%d", psRefCountCCBEntry->pcMesg,
+ psRefCountCCBEntry->ui32PID,
+ psRefCountCCBEntry->pszFile,
+ psRefCountCCBEntry->iLine));
+ }
+
+ PVRSRV_UNLOCK_CCB();
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "SYNCINFO",
+ psKernelSyncInfo,
+ psKernelMemInfo,
+ NULL,
+ (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+ ui32RefValue,
+ ui32RefValue + 1,
+ (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ IMG_UINT32 ui32RefValue = OSAtomicRead(psKernelSyncInfo->pvRefCount);
+
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_SYNCINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "SYNCINFO",
+ psKernelSyncInfo,
+ psKernelMemInfo,
+ (psKernelMemInfo) ? psKernelMemInfo->sMemBlk.hOSMemHandle : NULL,
+ NULL,
+ ui32RefValue,
+ ui32RefValue - 1,
+ (psKernelMemInfo) ? psKernelMemInfo->uAllocSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MEMINFO",
+ psKernelMemInfo->psKernelSyncInfo,
+ psKernelMemInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ NULL,
+ psKernelMemInfo->ui32RefCount,
+ psKernelMemInfo->ui32RefCount + 1,
+ psKernelMemInfo->uAllocSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psKernelMemInfo->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MEMINFO))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MEMINFO",
+ psKernelMemInfo->psKernelSyncInfo,
+ psKernelMemInfo,
+ psKernelMemInfo->sMemBlk.hOSMemHandle,
+ NULL,
+ psKernelMemInfo->ui32RefCount,
+ psKernelMemInfo->ui32RefCount - 1,
+ psKernelMemInfo->uAllocSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psKernelMemInfo->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32RefCount,
+ pBuf->ui32RefCount + 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32RefCount,
+ pBuf->ui32RefCount - 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF2",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32ExportCount,
+ pBuf->ui32ExportCount + 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32ExportCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile, IMG_INT iLine, BM_BUF *pBuf)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_BUF2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_BUF2",
+ NULL,
+ NULL,
+ BM_HandleToOSMemHandle(pBuf),
+ pBuf,
+ pBuf->ui32ExportCount,
+ pBuf->ui32ExportCount - 1,
+ (pBuf->pMapping) ? pBuf->pMapping->uSize : 0);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ pBuf->ui32ExportCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_XPROC",
+ NULL,
+ NULL,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+ (IMG_VOID *) ui32Index,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount + 1,
+ gXProcWorkaroundShareData[ui32Index].ui32Size);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_BM_XPROC))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "BM_XPROC",
+ NULL,
+ NULL,
+ gXProcWorkaroundShareData[ui32Index].hOSMemHandle,
+ (IMG_VOID *) ui32Index,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount,
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount - 1,
+ gXProcWorkaroundShareData[ui32Index].ui32Size);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32RefCount + 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32RefCount++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32RefCount,
+ psOffsetStruct->ui32RefCount - 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32RefCount--;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP2",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32Mapped,
+ psOffsetStruct->ui32Mapped + 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32Mapped++;
+}
+
+IMG_INTERNAL
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ if(!(guiDebugMask & PVRSRV_REFCOUNT_CCB_DEBUG_MMAP2))
+ goto skip;
+
+ PVRSRV_LOCK_CCB();
+
+ gsRefCountCCB[giOffset].pszFile = pszFile;
+ gsRefCountCCB[giOffset].iLine = iLine;
+ gsRefCountCCB[giOffset].ui32PID = OSGetCurrentProcessIDKM();
+ snprintf(gsRefCountCCB[giOffset].pcMesg,
+ PVRSRV_REFCOUNT_CCB_MESG_MAX - 1,
+ PVRSRV_REFCOUNT_CCB_FMT_STRING,
+ "MMAP2",
+ NULL,
+ NULL,
+ psOffsetStruct->psLinuxMemArea,
+ psOffsetStruct,
+ psOffsetStruct->ui32Mapped,
+ psOffsetStruct->ui32Mapped - 1,
+ psOffsetStruct->ui32RealByteSize);
+ gsRefCountCCB[giOffset].pcMesg[PVRSRV_REFCOUNT_CCB_MESG_MAX - 1] = 0;
+ giOffset = (giOffset + 1) % PVRSRV_REFCOUNT_CCB_MAX;
+
+ PVRSRV_UNLOCK_CCB();
+
+skip:
+ psOffsetStruct->ui32Mapped--;
+}
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
diff --git a/sgx/services4/srvkm/common/resman.c b/sgx/services4/srvkm/common/resman.c
index 5088c7f..e0f165c 100644
--- a/sgx/services4/srvkm/common/resman.c
+++ b/sgx/services4/srvkm/common/resman.c
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Resource Manager
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "resman.h"
@@ -81,49 +97,56 @@ static DECLARE_MUTEX(lock);
#define RESMAN_SIGNATURE 0x12345678
+/******************************************************************************
+ * resman structures
+ *****************************************************************************/
+
+/* resman item structure */
typedef struct _RESMAN_ITEM_
{
#ifdef DEBUG
IMG_UINT32 ui32Signature;
#endif
- struct _RESMAN_ITEM_ **ppsThis;
- struct _RESMAN_ITEM_ *psNext;
+ struct _RESMAN_ITEM_ **ppsThis; /*!< list navigation */
+ struct _RESMAN_ITEM_ *psNext; /*!< list navigation */
- IMG_UINT32 ui32Flags;
- IMG_UINT32 ui32ResType;
+ IMG_UINT32 ui32Flags; /*!< flags */
+ IMG_UINT32 ui32ResType;/*!< res type */
- IMG_PVOID pvParam;
- IMG_UINT32 ui32Param;
+ IMG_PVOID pvParam; /*!< param1 for callback */
+ IMG_UINT32 ui32Param; /*!< param2 for callback */
- RESMAN_FREE_FN pfnFreeResource;
+ RESMAN_FREE_FN pfnFreeResource;/*!< resman item free callback */
} RESMAN_ITEM;
+/* resman context structure */
typedef struct _RESMAN_CONTEXT_
{
#ifdef DEBUG
IMG_UINT32 ui32Signature;
#endif
- struct _RESMAN_CONTEXT_ **ppsThis;
- struct _RESMAN_CONTEXT_ *psNext;
+ struct _RESMAN_CONTEXT_ **ppsThis;/*!< list navigation */
+ struct _RESMAN_CONTEXT_ *psNext;/*!< list navigation */
- PVRSRV_PER_PROCESS_DATA *psPerProc;
+ PVRSRV_PER_PROCESS_DATA *psPerProc; /* owner of resources */
- RESMAN_ITEM *psResItemList;
+ RESMAN_ITEM *psResItemList;/*!< res item list for context */
} RESMAN_CONTEXT;
+/* resman list structure */
typedef struct
{
- RESMAN_CONTEXT *psContextList;
+ RESMAN_CONTEXT *psContextList; /*!< resman context list */
-} RESMAN_LIST, *PRESMAN_LIST;
+} RESMAN_LIST, *PRESMAN_LIST; /* PRQA S 3205 */
PRESMAN_LIST gpsResList = IMG_NULL;
-#include "lists.h"
+#include "lists.h" /* PRQA S 5087 */ /* include lists.h required here */
static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
@@ -137,6 +160,8 @@ static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
#define PRINT_RESLIST(x, y, z)
+/******************************************************** Forword references */
+
static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback, IMG_BOOL bForceCleanup);
static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
@@ -159,11 +184,21 @@ static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
+/*!
+******************************************************************************
+
+ @Function ResManInit
+
+ @Description initialises the resman
+
+ @Return none
+
+******************************************************************************/
PVRSRV_ERROR ResManInit(IMG_VOID)
{
if (gpsResList == IMG_NULL)
{
-
+ /* If not already initialised */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(*gpsResList),
(IMG_VOID **)&gpsResList, IMG_NULL,
@@ -172,10 +207,10 @@ PVRSRV_ERROR ResManInit(IMG_VOID)
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* Init list, the linked list has dummy entries at both ends */
gpsResList->psContextList = IMG_NULL;
-
+ /* Check resource list */
VALIDATERESLIST();
}
@@ -183,30 +218,52 @@ PVRSRV_ERROR ResManInit(IMG_VOID)
}
+/*!
+******************************************************************************
+
+ @Function ResManDeInit
+
+ @Description de-initialises the resman
+
+ @Return none
+
+******************************************************************************/
IMG_VOID ResManDeInit(IMG_VOID)
{
if (gpsResList != IMG_NULL)
{
-
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
gpsResList = IMG_NULL;
}
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManConnect
+
+ @Description Opens a connection to the Resource Manager
+
+ @input hPerProc - Per-process data (if applicable)
+ @output phResManContext - Resman context
+
+ @Return error code or PVRSRV_OK
+
+******************************************************************************/
PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
PRESMAN_CONTEXT *phResManContext)
{
PVRSRV_ERROR eError;
PRESMAN_CONTEXT psResManContext;
-
+ /*Acquire resource list sync object*/
ACQUIRE_SYNC_OBJ;
-
+ /*Check resource list*/
VALIDATERESLIST();
-
+ /* Allocate memory for the new context. */
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
(IMG_VOID **)&psResManContext, IMG_NULL,
"Resource Manager Context");
@@ -214,10 +271,10 @@ PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
{
PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return eError;
@@ -225,17 +282,17 @@ PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
#ifdef DEBUG
psResManContext->ui32Signature = RESMAN_SIGNATURE;
-#endif
+#endif /* DEBUG */
psResManContext->psResItemList = IMG_NULL;
psResManContext->psPerProc = hPerProc;
-
+ /* Insert new context struct after the dummy first entry */
List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
*phResManContext = psResManContext;
@@ -244,38 +301,51 @@ PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVResManDisconnect
+
+ @Description Closes a Resource Manager connection and frees all resources
+
+ @input hResManContext - Resman context
+ @input bKernelContext - IMG_TRUE for kernel contexts
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
IMG_BOOL bKernelContext)
{
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Print and validate resource list */
PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
-
+ /* Free all auto-freed resources in order */
if (!bKernelContext)
{
-
+ /* OS specific User-mode Mappings: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
-
+ /* VGX types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, 0, 0, IMG_TRUE);
-
+ /* Event Object */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
-
-
+ /* syncobject state (Read/Write Complete values) */
+ /* Must be FIFO, so we reverse the list, twice */
List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
- List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList);
+ List_RESMAN_ITEM_Reverse(&psResManContext->psResItemList); // (could survive without this - all following items would be cleared up "fifo" too)
-
+ /* SGX types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
@@ -283,9 +353,7 @@ IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
-
-
-
+ /* COMMON types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SYNC_INFO, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
@@ -294,37 +362,57 @@ IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_MEM_INFO, 0, 0, IMG_TRUE);
-
-
+#if defined(SUPPORT_ION)
+ FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ION, 0, 0, IMG_TRUE);
+#endif
+ /* DISPLAY CLASS types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
-
+ /* BUFFER CLASS types: */
FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
}
-
+ /* Ensure that there are no resources left */
PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
-
+ /* Remove the context struct from the list */
List_RESMAN_CONTEXT_Remove(psResManContext);
-
+ /* Free the context struct */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Print and validate resource list */
PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
}
+/*!
+******************************************************************************
+ @Function ResManRegisterRes
+
+ @Description : Inform the resource manager that the given resource has
+ been alloacted and freeing of it will be the responsibility
+ of the resource manager
+
+ @input psResManContext - resman context
+ @input ui32ResType - identify what kind of resource it is
+ @input pvParam - address of resource
+ @input ui32Param - size of resource
+ @input pfnFreeResource - pointer to function that frees this resource
+
+ @Return On success a pointer to an opaque data structure that represents
+ the allocated resource, else NULL
+
+**************************************************************************/
PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
IMG_UINT32 ui32ResType,
IMG_PVOID pvParam,
@@ -342,10 +430,10 @@ PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
return (PRESMAN_ITEM) IMG_NULL;
}
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
+ /* Check resource list */
VALIDATERESLIST();
PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
@@ -357,7 +445,7 @@ PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
ui32Param,
(IMG_UINTPTR_T)pfnFreeResource));
-
+ /* Allocate memory for the new resource structure */
if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
IMG_NULL,
@@ -366,34 +454,45 @@ PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
"ERROR allocating new resource item"));
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return((PRESMAN_ITEM)IMG_NULL);
}
-
+ /* Fill in details about this resource */
#ifdef DEBUG
psNewResItem->ui32Signature = RESMAN_SIGNATURE;
-#endif
+#endif /* DEBUG */
psNewResItem->ui32ResType = ui32ResType;
psNewResItem->pvParam = pvParam;
psNewResItem->ui32Param = ui32Param;
psNewResItem->pfnFreeResource = pfnFreeResource;
psNewResItem->ui32Flags = 0;
-
+ /* Insert new structure after dummy first entry */
List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return(psNewResItem);
}
+/*!
+******************************************************************************
+ @Function ResManFreeResByPtr
+
+ @Description frees a resource by matching on pointer type
+
+ @inputs psResItem - pointer to resource item to free
+ bForceCleanup - ignored uKernel re-sync
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem, IMG_BOOL bForceCleanup)
{
PVRSRV_ERROR eError;
@@ -409,25 +508,40 @@ PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem, IMG_BOOL bForceCleanup)
PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X",
(IMG_UINTPTR_T)psResItem));
-
+ /*Acquire resource list sync object*/
ACQUIRE_SYNC_OBJ;
-
+ /*Check resource list*/
VALIDATERESLIST();
-
+ /*Free resource*/
eError = FreeResourceByPtr(psResItem, IMG_TRUE, bForceCleanup);
-
+ /*Check resource list*/
VALIDATERESLIST();
-
+ /*Release resource list sync object*/
RELEASE_SYNC_OBJ;
return(eError);
}
+/*!
+******************************************************************************
+ @Function ResManFreeResByCriteria
+
+ @Description frees a resource by matching on criteria
+
+ @inputs hResManContext - handle for resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be
+ used in search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+ @inputs ui32Param - size of resource to be free
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
IMG_UINT32 ui32SearchCriteria,
IMG_UINT32 ui32ResType,
@@ -438,10 +552,10 @@ PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
PVR_ASSERT(psResManContext != IMG_NULL);
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
+ /* Check resource list */
VALIDATERESLIST();
PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
@@ -449,21 +563,32 @@ PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
(IMG_UINTPTR_T)psResManContext, ui32SearchCriteria, ui32ResType,
(IMG_UINTPTR_T)pvParam, ui32Param));
-
+ /* Free resources by criteria for this context */
eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
ui32ResType, pvParam, ui32Param,
IMG_TRUE);
-
+ /* Check resource list */
VALIDATERESLIST();
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
return eError;
}
+/*!
+******************************************************************************
+ @Function ResManDissociateRes
+
+ @Description Moves a resource from one context to another.
+
+ @inputs psResItem - pointer to resource item to dissociate
+ @inputs psNewResManContext - new resman context for the resource
+
+ @Return IMG_VOID
+**************************************************************************/
PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
PRESMAN_CONTEXT psNewResManContext)
{
@@ -478,16 +603,16 @@ PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-#ifdef DEBUG
+#ifdef DEBUG /* QAC fix */
PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
#endif
if (psNewResManContext != IMG_NULL)
{
-
+ /* Remove this item from its old resource list */
List_RESMAN_ITEM_Remove(psResItem);
-
+ /* Re-insert into new list */
List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
}
@@ -504,6 +629,19 @@ PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
return eError;
}
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr_AnyVaCb
+
+ @Description
+ Compares the resman item with a given pointer.
+
+ @inputs psCurItem - theThe item to check
+ @inputs va - Variable argument list with:
+ psItem - pointer to resource item to find
+
+ @Return IMG_BOOL
+**************************************************************************/
static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
{
RESMAN_ITEM *psItem;
@@ -514,9 +652,23 @@ static IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list
}
+/*!
+******************************************************************************
+ @Function ResManFindResourceByPtr
+
+ @Description
+ Attempts to find a resource in the list for this context
+
+ @inputs hResManContext - handle for resman context
+ @inputs psItem - pointer to resource item to find
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
RESMAN_ITEM *psItem)
{
+/* RESMAN_ITEM *psCurItem;*/
+
PVRSRV_ERROR eResult;
PVR_ASSERT(psResManContext != IMG_NULL);
@@ -529,11 +681,11 @@ IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContex
return PVRSRV_ERROR_INVALID_PARAMS;
}
-#ifdef DEBUG
+#ifdef DEBUG /* QAC fix */
PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
#endif
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
PVR_DPF((PVR_DBG_MESSAGE,
@@ -550,7 +702,7 @@ IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContex
(IMG_UINTPTR_T)psItem->pfnFreeResource,
psItem->ui32Flags));
-
+ /* Search resource items starting at after the first dummy item */
if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
&ResManFindResourceByPtr_AnyVaCb,
psItem))
@@ -562,12 +714,28 @@ IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContex
eResult = PVRSRV_ERROR_NOT_OWNER;
}
-
+ /* Release resource list sync object */
RELEASE_SYNC_OBJ;
+/* return PVRSRV_ERROR_NOT_OWNER;*/
return eResult;
}
+/*!
+******************************************************************************
+ @Function FreeResourceByPtr
+
+ @Description
+ Frees a resource and move it from the list
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psItem - pointer to resource item to free
+ bExecuteCallback - execute callback?
+ bForceCleanup - skips uKernel re-sync
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
IMG_BOOL bExecuteCallback,
IMG_BOOL bForceCleanup)
@@ -582,7 +750,7 @@ static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-#ifdef DEBUG
+#ifdef DEBUG /* QAC fix */
PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
#endif
@@ -597,32 +765,52 @@ static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
(IMG_UINTPTR_T)psItem->pvParam, psItem->ui32Param,
(IMG_UINTPTR_T)psItem->pfnFreeResource, psItem->ui32Flags));
-
- List_RESMAN_ITEM_Remove(psItem);
-
-
-
+ /* Release resource list sync object just in case the free routine calls the resource manager */
RELEASE_SYNC_OBJ;
-
+ /* Call the freeing routine */
if (bExecuteCallback)
{
eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param, bForceCleanup);
- if (eError != PVRSRV_OK)
+ if ((eError != PVRSRV_OK) && (eError != PVRSRV_ERROR_RETRY))
{
PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
}
}
-
+ /* Acquire resource list sync object */
ACQUIRE_SYNC_OBJ;
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Remove this item from the resource list */
+ List_RESMAN_ITEM_Remove(psItem);
+
+ /* Free memory for the resource item */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL);
+ }
return(eError);
}
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria_AnyVaCb
+
+ @Description
+ Matches a resource manager item with a given criteria.
+
+ @inputs psCuItem - the item to be matched
+ @inputs va - a variable argument list with:.
+ ui32SearchCriteria - indicates which parameters should be used
+ search for resources to free
+ ui32ResType - identify what kind of resource to free
+ pvParam - address of resource to be free
+ ui32Param - size of resource to be free
+
+
+ @Return psCurItem if matched, IMG_NULL otherwise.
+**************************************************************************/
static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
{
IMG_UINT32 ui32SearchCriteria;
@@ -635,17 +823,17 @@ static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list
pvParam = va_arg(va, IMG_PVOID);
ui32Param = va_arg(va, IMG_UINT32);
-
+ /*check that for all conditions are either disabled or eval to true*/
if(
-
+ /* Check resource type */
(((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
(psCurItem->ui32ResType == ui32ResType))
&&
-
+ /* Check address */
(((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
(psCurItem->pvParam == pvParam))
&&
-
+ /* Check size */
(((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
(psCurItem->ui32Param == ui32Param))
)
@@ -658,6 +846,27 @@ static IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list
}
}
+/*!
+******************************************************************************
+ @Function FreeResourceByCriteria
+
+ @Description
+ Frees all resources that match the given criteria for the
+ context.
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @inputs psResManContext - pointer to resman context
+ @inputs ui32SearchCriteria - indicates which parameters should be used
+ @inputs search for resources to free
+ @inputs ui32ResType - identify what kind of resource to free
+ @inputs pvParam - address of resource to be free
+ @inputs ui32Param - size of resource to be free
+ @inputs ui32AutoFreeLev - auto free level to free
+ @inputs bExecuteCallback - execute callback?
+
+ @Return PVRSRV_ERROR
+**************************************************************************/
static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
IMG_UINT32 ui32SearchCriteria,
IMG_UINT32 ui32ResType,
@@ -668,8 +877,8 @@ static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
PRESMAN_ITEM psCurItem;
PVRSRV_ERROR eError = PVRSRV_OK;
-
-
+ /* Search resource items starting at after the first dummy item */
+ /*while we get a match and not an error*/
while((psCurItem = (PRESMAN_ITEM)
List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
&FreeResourceByCriteria_AnyVaCb,
@@ -679,7 +888,19 @@ static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
ui32Param)) != IMG_NULL
&& eError == PVRSRV_OK)
{
- eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+ do
+ {
+ eError = FreeResourceByPtr(psCurItem, bExecuteCallback, CLEANUP_WITH_POLL);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ RELEASE_SYNC_OBJ;
+ OSReleaseBridgeLock();
+ /* Give a chance for other threads to come in and SGX to do more work */
+ OSSleepms(MAX_CLEANUP_TIME_WAIT_US/1000);
+ OSReacquireBridgeLock();
+ ACQUIRE_SYNC_OBJ;
+ }
+ } while (eError == PVRSRV_ERROR_RETRY);
}
return eError;
@@ -687,12 +908,23 @@ static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
#ifdef DEBUG
+/*!
+******************************************************************************
+ @Function ValidateResList
+
+ @Description
+ Walks the resource list check the pointers
+ NOTE : this function must be called with the resource
+ list sync object held
+
+ @Return none
+**************************************************************************/
static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
{
PRESMAN_ITEM psCurItem, *ppsThisItem;
PRESMAN_CONTEXT psCurContext, *ppsThisContext;
-
+ /* check we're initialised */
if (psResList == IMG_NULL)
{
PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
@@ -702,10 +934,10 @@ static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
psCurContext = psResList->psContextList;
ppsThisContext = &psResList->psContextList;
-
+ /* Walk the context list */
while(psCurContext != IMG_NULL)
{
-
+ /* Check current item */
PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
if (psCurContext->ppsThis != ppsThisContext)
{
@@ -718,12 +950,12 @@ static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
}
-
+ /* Walk the list for this context */
psCurItem = psCurContext->psResItemList;
ppsThisItem = &psCurContext->psResItemList;
while(psCurItem != IMG_NULL)
{
-
+ /* Check current item */
PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
if (psCurItem->ppsThis != ppsThisItem)
{
@@ -736,16 +968,19 @@ static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
}
-
+ /* Move to next item */
ppsThisItem = &psCurItem->psNext;
psCurItem = psCurItem->psNext;
}
-
+ /* Move to next context */
ppsThisContext = &psCurContext->psNext;
psCurContext = psCurContext->psNext;
}
}
-#endif
+#endif /* DEBUG */
+/******************************************************************************
+ End of file (resman.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/mmu.c b/sgx/services4/srvkm/devices/sgx/mmu.c
index 9fa93d0..7f1fe9c 100644
--- a/sgx/services4/srvkm/devices/sgx/mmu.c
+++ b/sgx/services4/srvkm/devices/sgx/mmu.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "sgxdefs.h"
#include "sgxmmu.h"
@@ -41,34 +58,79 @@
#define UINT32_MAX_VALUE 0xFFFFFFFFUL
+/*
+ MMU performs device virtual to physical translation.
+ terminology:
+ page directory (PD)
+ pagetable (PT)
+ data page (DP)
+
+ Incoming 32bit Device Virtual Addresses are deconstructed into 3 fields:
+ ---------------------------------------------------------
+ | PD Index/tag: | PT Index: | DP offset: |
+ | bits 31:22 | bits 21:n | bits (n-1):0 |
+ ---------------------------------------------------------
+ where typically n=12 for a standard 4k DP
+ but n=16 for a 64k DP
+
+ MMU page directory (PD), pagetable (PT) and data page (DP) config:
+ PD:
+ - always one page per address space
+ - up to 4k in size to span 4Gb (32bit)
+ - contains up to 1024 32bit entries
+ - entries are indexed by the top 12 bits of an incoming 32bit device virtual address
+ - the PD entry selected contains the physical address of the PT to
+ perform the next stage of the V to P translation
+
+ PT:
+ - size depends on the DP size, e.g. 4k DPs have 4k PTs but 16k DPs have 1k PTs
+ - each PT always spans 4Mb of device virtual address space irrespective of DP size
+ - number of entries in a PT depend on DP size and ranges from 1024 to 4 entries
+ - entries are indexed by the PT Index field of the device virtual address (21:n)
+ - the PT entry selected contains the physical address of the DP to access
+
+ DP:
+ - size varies from 4k to 4M in multiple of 4 steppings
+ - DP offset field of the device virtual address ((n-1):0) is used as a byte offset
+ to address into the DP itself
+*/
+
#define SGX_MAX_PD_ENTRIES (1<<(SGX_FEATURE_ADDRESS_SPACE_SIZE - SGX_MMU_PT_SHIFT - SGX_MMU_PAGE_SHIFT))
#if defined(FIX_HW_BRN_31620)
-#define SGX_MMU_PDE_DUMMY_PAGE (0)
-#define SGX_MMU_PTE_DUMMY_PAGE (0)
+/* Sim doesn't use the address mask */
+#define SGX_MMU_PDE_DUMMY_PAGE (0)//(0x00000020U)
+#define SGX_MMU_PTE_DUMMY_PAGE (0)//(0x00000020U)
+/* 4MB adress range per page table */
#define BRN31620_PT_ADDRESS_RANGE_SHIFT 22
#define BRN31620_PT_ADDRESS_RANGE_SIZE (1 << BRN31620_PT_ADDRESS_RANGE_SHIFT)
+/* 64MB address range per PDE cache line */
#define BRN31620_PDE_CACHE_FILL_SHIFT 26
#define BRN31620_PDE_CACHE_FILL_SIZE (1 << BRN31620_PDE_CACHE_FILL_SHIFT)
#define BRN31620_PDE_CACHE_FILL_MASK (BRN31620_PDE_CACHE_FILL_SIZE - 1)
+/* Page Directory Enteries per cache line */
#define BRN31620_PDES_PER_CACHE_LINE_SHIFT (BRN31620_PDE_CACHE_FILL_SHIFT - BRN31620_PT_ADDRESS_RANGE_SHIFT)
#define BRN31620_PDES_PER_CACHE_LINE_SIZE (1 << BRN31620_PDES_PER_CACHE_LINE_SHIFT)
#define BRN31620_PDES_PER_CACHE_LINE_MASK (BRN31620_PDES_PER_CACHE_LINE_SIZE - 1)
+/* Macros for working out offset for dummy pages */
#define BRN31620_DUMMY_PAGE_OFFSET (1 * SGX_MMU_PAGE_SIZE)
#define BRN31620_DUMMY_PDE_INDEX (BRN31620_DUMMY_PAGE_OFFSET / BRN31620_PT_ADDRESS_RANGE_SIZE)
#define BRN31620_DUMMY_PTE_INDEX ((BRN31620_DUMMY_PAGE_OFFSET - (BRN31620_DUMMY_PDE_INDEX * BRN31620_PT_ADDRESS_RANGE_SIZE))/SGX_MMU_PAGE_SIZE)
+/* Cache number of cache lines */
#define BRN31620_CACHE_FLUSH_SHIFT (32 - BRN31620_PDE_CACHE_FILL_SHIFT)
#define BRN31620_CACHE_FLUSH_SIZE (1 << BRN31620_CACHE_FLUSH_SHIFT)
+/* Cache line bits in a UINT32 */
#define BRN31620_CACHE_FLUSH_BITS_SHIFT 5
#define BRN31620_CACHE_FLUSH_BITS_SIZE (1 << BRN31620_CACHE_FLUSH_BITS_SHIFT)
#define BRN31620_CACHE_FLUSH_BITS_MASK (BRN31620_CACHE_FLUSH_BITS_SIZE - 1)
+/* Cache line index in array */
#define BRN31620_CACHE_FLUSH_INDEX_BITS (BRN31620_CACHE_FLUSH_SHIFT - BRN31620_CACHE_FLUSH_BITS_SHIFT)
#define BRN31620_CACHE_FLUSH_INDEX_SIZE (1 << BRN31620_CACHE_FLUSH_INDEX_BITS)
@@ -77,26 +139,44 @@
typedef struct _MMU_PT_INFO_
{
-
+ /* note: may need a union here to accommodate a PT page address for local memory */
IMG_VOID *hPTPageOSMemHandle;
IMG_CPU_VIRTADDR PTPageCpuVAddr;
-
-
+ /* Map of reserved PTEs.
+ * Reserved PTEs are like "valid" PTEs in that they (and the DevVAddrs they represent)
+ * cannot be assigned to another allocation but their "reserved" status persists through
+ * any amount of mapping and unmapping, until the allocation is finally destroyed.
+ *
+ * Reserved and Valid are independent.
+ * When a PTE is first reserved, it will have Reserved=1 and Valid=0.
+ * When the PTE is actually mapped, it will have Reserved=1 and Valid=1.
+ * When the PTE is unmapped, it will have Reserved=1 and Valid=0.
+ * At this point, the PT will can not be destroyed because although there is
+ * not an active mapping on the PT, it is known a PTE is reserved for use.
+ *
+ * The above sequence of mapping and unmapping may repeat any number of times
+ * until the allocation is unmapped and destroyed which causes the PTE to have
+ * Valid=0 and Reserved=0.
+ */
+ /* Number of PTEs set up.
+ * i.e. have a valid SGX Phys Addr and the "VALID" PTE bit == 1
+ */
IMG_UINT32 ui32ValidPTECount;
} MMU_PT_INFO;
+#define MMU_CONTEXT_NAME_SIZE 50
struct _MMU_CONTEXT_
{
-
+ /* the device node */
PVRSRV_DEVICE_NODE *psDeviceNode;
-
+ /* Page Directory CPUVirt and DevPhys Addresses */
IMG_CPU_VIRTADDR pvPDCpuVAddr;
IMG_DEV_PHYADDR sPDDevPAddr;
IMG_VOID *hPDOSMemHandle;
-
+ /* information about dynamically allocated pagetables */
MMU_PT_INFO *apsPTInfoList[SGX_MAX_PD_ENTRIES];
PVRSRV_SGXDEV_INFO *psDevInfo;
@@ -108,6 +188,9 @@ struct _MMU_CONTEXT_
#endif
#endif
+ IMG_UINT32 ui32PID;
+ IMG_CHAR szName[MMU_CONTEXT_NAME_SIZE];
+
#if defined (FIX_HW_BRN_31620)
IMG_UINT32 ui32PDChangeMask[BRN31620_CACHE_FLUSH_INDEX_SIZE];
IMG_UINT32 ui32PDCacheRangeRefCount[BRN31620_CACHE_FLUSH_SIZE];
@@ -118,57 +201,65 @@ struct _MMU_CONTEXT_
struct _MMU_HEAP_
{
-
+ /* MMU context */
MMU_CONTEXT *psMMUContext;
-
-
-
+ /*
+ heap specific details:
+ */
+ /* the Base PD index for the heap */
IMG_UINT32 ui32PDBaseIndex;
-
+ /* number of pagetables in this heap */
IMG_UINT32 ui32PageTableCount;
-
+ /* total number of pagetable entries in this heap which may be mapped to data pages */
IMG_UINT32 ui32PTETotalUsable;
-
+ /* PD entry DP size control field */
IMG_UINT32 ui32PDEPageSizeCtrl;
-
-
-
+ /*
+ Data Page (DP) Details:
+ */
+ /* size in bytes of a data page */
IMG_UINT32 ui32DataPageSize;
-
+ /* bit width of the data page offset addressing field */
IMG_UINT32 ui32DataPageBitWidth;
-
+ /* bit mask of the data page offset addressing field */
IMG_UINT32 ui32DataPageMask;
-
-
-
+ /*
+ PageTable (PT) Details:
+ */
+ /* bit shift to base of PT addressing field */
IMG_UINT32 ui32PTShift;
-
+ /* bit width of the PT addressing field */
IMG_UINT32 ui32PTBitWidth;
-
+ /* bit mask of the PT addressing field */
IMG_UINT32 ui32PTMask;
-
+ /* size in bytes of a pagetable */
IMG_UINT32 ui32PTSize;
-
+ /* Allocated PT Entries per PT */
IMG_UINT32 ui32PTNumEntriesAllocated;
-
+ /* Usable PT Entries per PT (may be different to num allocated for 4MB data page) */
IMG_UINT32 ui32PTNumEntriesUsable;
-
-
-
+ /*
+ PageDirectory Details:
+ */
+ /* bit shift to base of PD addressing field */
IMG_UINT32 ui32PDShift;
-
+ /* bit width of the PD addressing field */
IMG_UINT32 ui32PDBitWidth;
-
+ /* bit mask of the PT addressing field */
IMG_UINT32 ui32PDMask;
-
-
+ /*
+ Arena Info:
+ */
RA_ARENA *psVMArena;
DEV_ARENA_DESCRIPTOR *psDevArena;
+
+ /* If we have sparse mappings then we can't do PT level sanity checks */
+ IMG_BOOL bHasSparseMappings;
#if defined(PDUMP)
PDUMP_MMU_ATTRIB sMMUAttrib;
#endif
@@ -180,6 +271,7 @@ struct _MMU_HEAP_
#define DUMMY_DATA_PAGE_SIGNATURE 0xDEADBEEF
#endif
+/* local prototypes: */
static IMG_VOID
_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT);
@@ -190,61 +282,241 @@ MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
IMG_SIZE_T uSize,
IMG_BOOL bForUnmap,
IMG_HANDLE hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
+/* This option tests page table memory, for use during device bring-up. */
#define PAGE_TEST 0
#if PAGE_TEST
static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr);
#endif
+/* This option dumps out the PT if an assert fails */
+#define PT_DUMP 1
+
+/* This option sanity checks page table PTE valid count matches active PTEs */
#define PT_DEBUG 0
-#if PT_DEBUG
+#if (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF)
static IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
{
IMG_UINT32 *p = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
IMG_UINT32 i;
-
+ /* 1024 entries in a 4K page table */
for(i = 0; i < 1024; i += 8)
{
- PVR_DPF((PVR_DBG_WARNING,
+ PVR_DPF((PVR_DBG_ERROR,
"%08X %08X %08X %08X %08X %08X %08X %08X\n",
p[i + 0], p[i + 1], p[i + 2], p[i + 3],
p[i + 4], p[i + 5], p[i + 6], p[i + 7]));
}
}
+#else /* (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) */
+static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+{
+ PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+}
+#endif /* (PT_DEBUG || PT_DUMP) && defined(PVRSRV_NEED_PVR_DPF) */
+#if PT_DEBUG
static IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
{
IMG_UINT32 *p = (IMG_UINT32*) psPTInfoList->PTPageCpuVAddr;
IMG_UINT32 i, ui32Count = 0;
-
+ /* 1024 entries in a 4K page table */
for(i = 0; i < 1024; i++)
if(p[i] & SGX_MMU_PTE_VALID)
ui32Count++;
if(psPTInfoList->ui32ValidPTECount != ui32Count)
{
- PVR_DPF((PVR_DBG_WARNING, "ui32ValidPTECount: %u ui32Count: %u\n",
+ PVR_DPF((PVR_DBG_ERROR, "ui32ValidPTECount: %u ui32Count: %u\n",
psPTInfoList->ui32ValidPTECount, ui32Count));
DumpPT(psPTInfoList);
BUG();
}
}
-#else
-static INLINE IMG_VOID DumpPT(MMU_PT_INFO *psPTInfoList)
+#else /* PT_DEBUG */
+static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
{
PVR_UNREFERENCED_PARAMETER(psPTInfoList);
}
+#endif /* PT_DEBUG */
-static INLINE IMG_VOID CheckPT(MMU_PT_INFO *psPTInfoList)
+/*
+ Debug functionality that allows us to make the CPU
+ mapping of pagetable memory readonly and only make
+ it read/write when we alter it. This allows us
+ to check that our memory isn't being overwritten
+*/
+#if defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND)
+
+#include <linux/version.h>
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,38))
+#ifndef AUTOCONF_INCLUDED
+#include <linux/config.h>
+#endif
+#else
+#include <generated/autoconf.h>
+#endif
+
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+static IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
{
- PVR_UNREFERENCED_PARAMETER(psPTInfoList);
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ pte_t ptent;
+ spinlock_t *psPTLock;
+ IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+ struct mm_struct *psMM = current->active_mm;
+
+
+ psPGD = pgd_offset(psMM, ui32CPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPUD = pud_offset(psPGD, ui32CPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ui32CPUVAddr, &psPTLock);
+
+ ptent = ptep_modify_prot_start(psMM, ui32CPUVAddr, psPTE);
+ ptent = pte_mkwrite(ptent);
+ ptep_modify_prot_commit(psMM, ui32CPUVAddr, psPTE, ptent);
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ flush_tlb_all();
+}
+
+static IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+ pgd_t *psPGD;
+ pud_t *psPUD;
+ pmd_t *psPMD;
+ pte_t *psPTE;
+ pte_t ptent;
+ spinlock_t *psPTLock;
+ IMG_UINT32 ui32CPUVAddr = (IMG_UINT32) ulCPUVAddr;
+ struct mm_struct *psMM = current->active_mm;
+
+ OSWriteMemoryBarrier();
+
+ psPGD = pgd_offset(psMM, ui32CPUVAddr);
+ if (pgd_none(*psPGD) || pgd_bad(*psPGD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPUD = pud_offset(psPGD, ui32CPUVAddr);
+ if (pud_none(*psPUD) || pud_bad(*psPUD))
+ {
+ PVR_ASSERT(0);
+ }
+
+ psPMD = pmd_offset(psPUD, ui32CPUVAddr);
+ if (pmd_none(*psPMD) || pmd_bad(*psPMD))
+ {
+ PVR_ASSERT(0);
+ }
+
+
+ psPTE = (pte_t *)pte_offset_map_lock(psMM, psPMD, ui32CPUVAddr, &psPTLock);
+
+ ptent = ptep_modify_prot_start(psMM, ui32CPUVAddr, psPTE);
+ ptent = pte_wrprotect(ptent);
+ ptep_modify_prot_commit(psMM, ui32CPUVAddr, psPTE, ptent);
+ pte_unmap_unlock(psPTE, psPTLock);
+
+ flush_tlb_all();
+
}
-#endif
+#else /* defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND) */
+static INLINE IMG_VOID MakeKernelPageReadWrite(IMG_PVOID ulCPUVAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+static INLINE IMG_VOID MakeKernelPageReadOnly(IMG_PVOID ulCPUVAddr)
+{
+ PVR_UNREFERENCED_PARAMETER(ulCPUVAddr);
+}
+
+#endif /* defined(PVRSRV_MMU_MAKE_READWRITE_ON_DEMAND) */
+
+/*___________________________________________________________________________
+
+ Information for SUPPORT_PDUMP_MULTI_PROCESS feature.
+
+ The client marked for pdumping will set the bPDumpActive flag in
+ the MMU Context (see MMU_Initialise).
+
+ Shared heap allocations should be persistent so all apps which
+ are pdumped will see the allocation. Persistent flag over-rides
+ the bPDumpActive flag (see pdump_common.c/DbgWrite function).
+
+ The idea is to dump PT,DP for shared heap allocations, but only
+ dump the PDE if the allocation is mapped into the kernel or active
+ client context. This ensures if a background app allocates on a
+ shared heap then all clients can access it in the pdump toolchain.
+
+
+
+ PD PT DP
+ +-+
+ | |---> +-+
+ +-+ | |---> +-+
+ +-+ + +
+ +-+
+
+ PD allocation/free: pdump flags are 0 (only need PD for active apps)
+ PT allocation/free: pdump flags are 0
+ unless PT is for a shared heap, in which case persistent is set
+ PD entries (MMU init/insert shared heap):
+ only pdump if PDE is on the active MMU context, flags are 0
+ PD entries (PT alloc):
+ pdump flags are 0 if kernel heap
+ pdump flags are 0 if shared heap and PDE is on active MMU context
+ otherwise ignore.
+ PT entries pdump flags are 0
+ unless PTE is for a shared heap, in which case persistent is set
+
+ NOTE: PDump common code:-
+ PDumpMallocPages and PDumpMemKM also set the persistent flag for
+ shared heap allocations.
+
+ ___________________________________________________________________________
+*/
+
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_IsHeapShared
+
+ PURPOSE: Is this heap shared?
+ PARAMETERS: In: pMMU_Heap
+ RETURNS: true if heap is shared
+******************************************************************************/
IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
{
switch(pMMUHeap->psDevArena->DevMemHeapType)
@@ -264,78 +536,145 @@ IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMUHeap)
}
#ifdef SUPPORT_SGX_MMU_BYPASS
+/*!
+******************************************************************************
+ FUNCTION: EnableHostAccess
+
+ PURPOSE: Enables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
EnableHostAccess (MMU_CONTEXT *psMMUContext)
{
IMG_UINT32 ui32RegVal;
IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
-
-
-
+ /*
+ bypass the MMU for the host port requestor,
+ conserving bypass state of other requestors
+ */
ui32RegVal = OSReadHWReg(pvRegsBaseKM, EUR_CR_BIF_CTRL);
OSWriteHWReg(pvRegsBaseKM,
EUR_CR_BIF_CTRL,
ui32RegVal | EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
-
+ /* assume we're not wiping-out any other bits */
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
}
+/*!
+******************************************************************************
+ FUNCTION: DisableHostAccess
+
+ PURPOSE: Disables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
DisableHostAccess (MMU_CONTEXT *psMMUContext)
{
IMG_UINT32 ui32RegVal;
IMG_VOID *pvRegsBaseKM = psMMUContext->psDevInfo->pvRegsBaseKM;
-
-
-
-
+ /*
+ disable MMU-bypass for the host port requestor,
+ conserving bypass state of other requestors
+ and flushing all caches/tlbs
+ */
OSWriteHWReg(pvRegsBaseKM,
EUR_CR_BIF_CTRL,
ui32RegVal & ~EUR_CR_BIF_CTRL_MMU_BYPASS_HOST_MASK);
-
+ /* assume we're not wiping-out any other bits */
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, 0);
}
#endif
#if defined(SGX_FEATURE_SYSTEM_CACHE)
+/*!
+******************************************************************************
+ FUNCTION: MMU_InvalidateSystemLevelCache
+
+ PURPOSE: Invalidates the System Level Cache to purge stale PDEs and PTEs
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+
+******************************************************************************/
static IMG_VOID MMU_InvalidateSystemLevelCache(PVRSRV_SGXDEV_INFO *psDevInfo)
{
#if defined(SGX_FEATURE_MP)
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
#else
-
+ /* The MMU always bypasses the SLC */
PVR_UNREFERENCED_PARAMETER(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_MP */
}
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_InvalidateDirectoryCache
+ PURPOSE: Invalidates the page directory cache + page table cache + requestor TLBs
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+
+******************************************************************************/
IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo)
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
#if defined(SGX_FEATURE_SYSTEM_CACHE)
MMU_InvalidateSystemLevelCache(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_InvalidatePageTableCache
+
+ PURPOSE: Invalidates the page table cache + requestor TLBs
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+
+******************************************************************************/
static IMG_VOID MMU_InvalidatePageTableCache(PVRSRV_SGXDEV_INFO *psDevInfo)
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PT;
#if defined(SGX_FEATURE_SYSTEM_CACHE)
MMU_InvalidateSystemLevelCache(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
}
#if defined(FIX_HW_BRN_31620)
+/*!
+******************************************************************************
+ FUNCTION: BRN31620InvalidatePageTableEntry
+
+ PURPOSE: Frees page tables in PDE cache line chunks re-wiring the
+ dummy page when required
+
+ PARAMETERS: In: psMMUContext, ui32PDIndex, ui32PTIndex
+ RETURNS: None
+
+******************************************************************************/
static IMG_VOID BRN31620InvalidatePageTableEntry(MMU_CONTEXT *psMMUContext, IMG_UINT32 ui32PDIndex, IMG_UINT32 ui32PTIndex, IMG_UINT32 *pui32PTE)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psMMUContext->psDevInfo;
-
+ /*
+ * Note: We can't tell at this stage if this PT will be freed before
+ * the end of the function so we always wire up the dummy page to
+ * to the PT.
+ */
if (((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
&& (ui32PTIndex == BRN31620_DUMMY_PTE_INDEX))
{
@@ -350,6 +689,17 @@ static IMG_VOID BRN31620InvalidatePageTableEntry(MMU_CONTEXT *psMMUContext, IMG_
}
}
+/*!
+******************************************************************************
+ FUNCTION: BRN31620FreePageTable
+
+ PURPOSE: Frees page tables in PDE cache line chunks re-wiring the
+ dummy page when required
+
+ PARAMETERS: In: psMMUContext, ui32PDIndex
+ RETURNS: IMG_TRUE if we freed any PT's
+
+******************************************************************************/
static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDIndex)
{
MMU_CONTEXT *psMMUContext = psMMUHeap->psMMUContext;
@@ -360,13 +710,18 @@ static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDInde
PVR_ASSERT(psMMUHeap != IMG_NULL);
-
+ /*
+ * Clear the PT info for this PD index so even if we don't
+ * free the memory here apsPTInfoList[PDIndex] will trigger
+ * an "allocation" in _DeferredAllocPagetables which
+ * bumps up the refcount.
+ */
PVR_ASSERT(psMMUContext->apsPTInfoListSave[ui32PDIndex] == IMG_NULL);
psMMUContext->apsPTInfoListSave[ui32PDIndex] = psMMUContext->apsPTInfoList[ui32PDIndex];
psMMUContext->apsPTInfoList[ui32PDIndex] = IMG_NULL;
-
+ /* Check if this was the last PT in the cache line */
if (--psMMUContext->ui32PDCacheRangeRefCount[ui32PDCacheLine] == 0)
{
IMG_UINT32 i;
@@ -374,10 +729,10 @@ static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDInde
IMG_UINT32 ui32PDIndexEnd = ui32PDIndexStart + BRN31620_PDES_PER_CACHE_LINE_SIZE;
IMG_UINT32 ui32PDBitMaskIndex, ui32PDBitMaskShift;
-
+ /* Free all PT's in cache line */
for (i=ui32PDIndexStart;i<ui32PDIndexEnd;i++)
{
-
+ /* This PT is _really_ being freed now */
psMMUContext->apsPTInfoList[i] = psMMUContext->apsPTInfoListSave[i];
psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
_DeferredFreePageTable(psMMUHeap, i - psMMUHeap->ui32PDBaseIndex, IMG_TRUE);
@@ -386,22 +741,27 @@ static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDInde
ui32PDBitMaskIndex = ui32PDCacheLine >> BRN31620_CACHE_FLUSH_BITS_SHIFT;
ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
-
+ /* Check if this is a shared heap */
if (MMU_IsHeapShared(psMMUHeap))
{
-
+ /* Mark the remove of the Page Table from all memory contexts */
MMU_CONTEXT *psMMUContextWalker = (MMU_CONTEXT*) psMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
while(psMMUContextWalker)
{
psMMUContextWalker->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
-
+ /*
+ * We've just cleared a cache line's worth of PDE's so we need
+ * to wire up the dummy PT
+ */
+ MakeKernelPageReadWrite(psMMUContextWalker->pvPDCpuVAddr);
pui32Tmp = (IMG_UINT32 *) psMMUContextWalker->pvPDCpuVAddr;
pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_DUMMY_PAGE
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContextWalker->pvPDCpuVAddr);
PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContextWalker->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
@@ -412,17 +772,22 @@ static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDInde
{
psMMUContext->ui32PDChangeMask[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
-
+ /*
+ * We've just cleared a cache line's worth of PDE's so we need
+ * to wire up the dummy PT
+ */
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
pui32Tmp = (IMG_UINT32 *) psMMUContext->pvPDCpuVAddr;
pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_DUMMY_PAGE
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
PDUMPCOMMENT("BRN31620 Re-wire dummy PT due to releasing PT allocation block");
PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32Tmp[ui32PDIndexStart + BRN31620_DUMMY_PDE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
-
+ /* We've freed a cachline's worth of PDE's so trigger a PD cache flush */
bFreePTs = IMG_TRUE;
}
@@ -430,6 +795,18 @@ static IMG_BOOL BRN31620FreePageTable(MMU_HEAP *psMMUHeap, IMG_UINT32 ui32PDInde
}
#endif
+/*!
+******************************************************************************
+ FUNCTION: _AllocPageTableMemory
+
+ PURPOSE: Allocate physical memory for a page table
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ In: psPTInfoList - PT info
+ Out: psDevPAddr - device physical address for new PT
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failed
+******************************************************************************/
static IMG_BOOL
_AllocPageTableMemory (MMU_HEAP *pMMUHeap,
MMU_PT_INFO *psPTInfoList,
@@ -438,23 +815,33 @@ _AllocPageTableMemory (MMU_HEAP *pMMUHeap,
IMG_DEV_PHYADDR sDevPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
-
-
-
+ /*
+ depending on the specific system, pagetables are allocated from system memory
+ or device local memory. For now, just look for at least a valid local heap/arena
+ */
if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
{
-
+ //FIXME: replace with an RA, this allocator only handles 4k allocs
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- pMMUHeap->ui32PTSize,
- SGX_MMU_PAGE_SIZE,
- (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
- &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
+ pMMUHeap->ui32PTSize,
+ SGX_MMU_PAGE_SIZE,//FIXME: assume 4K page size for now (wastes memory for smaller pagetables
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ (IMG_VOID **)&psPTInfoList->PTPageCpuVAddr,
+ &psPTInfoList->hPTPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "_AllocPageTableMemory: ERROR call to OSAllocPages failed"));
return IMG_FALSE;
}
-
+ /*
+ Force the page to read only, we will make it read/write as
+ and when we need to
+ */
+ MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
+
+ /* translate address to device physical */
if(psPTInfoList->PTPageCpuVAddr)
{
sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
@@ -462,7 +849,8 @@ _AllocPageTableMemory (MMU_HEAP *pMMUHeap,
}
else
{
-
+ /* This isn't used in all cases since not all ports currently support
+ * OSMemHandleToCpuPAddr() */
sCpuPAddr = OSMemHandleToCpuPAddr(psPTInfoList->hPTPageOSMemHandle, 0);
}
@@ -472,16 +860,19 @@ _AllocPageTableMemory (MMU_HEAP *pMMUHeap,
{
IMG_SYS_PHYADDR sSysPAddr;
-
-
-
-
+ /*
+ just allocate from the first local memory arena
+ (unlikely to be more than one local mem area(?))
+ */
+ //FIXME: just allocate a 4K page for each PT for now
if(RA_Alloc(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena,
- SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,//pMMUHeap->ui32PTSize,
IMG_NULL,
IMG_NULL,
0,
- SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,//pMMUHeap->ui32PTSize,
+ 0,
+ IMG_NULL,
0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
@@ -489,9 +880,9 @@ _AllocPageTableMemory (MMU_HEAP *pMMUHeap,
return IMG_FALSE;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
-
+ /* note: actual ammount is pMMUHeap->ui32PTSize but must be a multiple of 4k pages */
psPTInfoList->PTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
@@ -502,7 +893,7 @@ _AllocPageTableMemory (MMU_HEAP *pMMUHeap,
return IMG_FALSE;
}
-
+ /* translate address to device physical */
sDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
#if PAGE_TEST
@@ -510,60 +901,76 @@ _AllocPageTableMemory (MMU_HEAP *pMMUHeap,
#endif
}
+ MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
{
IMG_UINT32 *pui32Tmp;
IMG_UINT32 i;
pui32Tmp = (IMG_UINT32*)psPTInfoList->PTPageCpuVAddr;
-
+ /* point the new PT entries to the dummy data page */
for(i=0; i<pMMUHeap->ui32PTNumEntriesUsable; i++)
{
pui32Tmp[i] = (pMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
}
-
+ /* zero the remaining allocated entries, if any */
for(; i<pMMUHeap->ui32PTNumEntriesAllocated; i++)
{
pui32Tmp[i] = 0;
}
}
#else
-
+ /* Zero the page table. */
OSMemSet(psPTInfoList->PTPageCpuVAddr, 0, pMMUHeap->ui32PTSize);
#endif
+ MakeKernelPageReadOnly(psPTInfoList->PTPageCpuVAddr);
#if defined(PDUMP)
{
IMG_UINT32 ui32Flags = 0;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* make sure shared heap PT allocs are always pdumped */
ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* pdump the PT malloc */
PDUMPMALLOCPAGETABLE(&pMMUHeap->psMMUContext->psDeviceNode->sDevId, psPTInfoList->hPTPageOSMemHandle, 0, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, PDUMP_PT_UNIQUETAG);
-
+ /* pdump the PT Pages */
PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfoList->hPTPageOSMemHandle, psPTInfoList->PTPageCpuVAddr, pMMUHeap->ui32PTSize, ui32Flags, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
-
-
+
+ /* return the DevPAddr */
*psDevPAddr = sDevPAddr;
return IMG_TRUE;
}
+/*!
+******************************************************************************
+ FUNCTION: _FreePageTableMemory
+
+ PURPOSE: Free physical memory for a page table
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ In: psPTInfoList - PT info to free
+ RETURNS: NONE
+******************************************************************************/
static IMG_VOID
_FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
{
-
-
-
-
+ /*
+ free the PT page:
+ depending on the specific system, pagetables are allocated from system memory
+ or device local memory. For now, just look for at least a valid local heap/arena
+ */
if(pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena == IMG_NULL)
{
-
+ /* Force the page to read write before we free it*/
+ MakeKernelPageReadWrite(psPTInfoList->PTPageCpuVAddr);
+
+ //FIXME: replace with an RA, this allocator only handles 4k allocs
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
pMMUHeap->ui32PTSize,
psPTInfoList->PTPageCpuVAddr,
@@ -574,27 +981,39 @@ _FreePageTableMemory (MMU_HEAP *pMMUHeap, MMU_PT_INFO *psPTInfoList)
IMG_SYS_PHYADDR sSysPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
-
+ /* derive the system physical address */
sCpuPAddr = OSMapLinToCPUPhys(psPTInfoList->hPTPageOSMemHandle,
psPTInfoList->PTPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr (sCpuPAddr);
-
-
+ /* unmap the CPU mapping */
+ /* note: actual ammount is pMMUHeap->ui32PTSize but must be a multiple of 4k pages */
OSUnMapPhysToLin(psPTInfoList->PTPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psPTInfoList->hPTPageOSMemHandle);
-
-
-
+ /*
+ just free from the first local memory arena
+ (unlikely to be more than one local mem area(?))
+ */
RA_Free (pMMUHeap->psDevArena->psDeviceMemoryHeapInfo->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
}
}
+/*!
+******************************************************************************
+ FUNCTION: _DeferredFreePageTable
+
+ PURPOSE: Free one page table associated with an MMU.
+
+ PARAMETERS: In: pMMUHeap - the mmu heap
+ In: ui32PTIndex - index of the page table to free relative
+ to the base of heap.
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
_DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOSFreePT)
{
@@ -606,10 +1025,10 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
SysAcquireData(&psSysData);
-
+ /* find the index/offset in PD entries */
ui32PDIndex = pMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* set the base PT info */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
{
@@ -617,11 +1036,11 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount > 0)
{
DumpPT(ppsPTInfoList[ui32PTIndex]);
-
+ /* Fall-through, will fail assert */
}
#endif
-
+ /* Assert that all mappings have gone */
PVR_ASSERT(ppsPTInfoList[ui32PTIndex] == IMG_NULL || ppsPTInfoList[ui32PTIndex]->ui32ValidPTECount == 0);
}
@@ -631,7 +1050,7 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
-
+ /* pdump the PT free */
PDUMPCOMMENT("Free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
if(ppsPTInfoList[ui32PTIndex] && ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr)
{
@@ -645,30 +1064,32 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
case DEVICE_MEMORY_HEAP_SHARED :
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
{
-
+ /* Remove Page Table from all memory contexts */
MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
while(psMMUContext)
{
-
+ /* get the PD CPUVAddr base and advance to the first entry */
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PD entry to the dummy PT */
pui32PDEntry[ui32PTIndex] = (psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_VALID;
#else
-
+ /* free the entry */
if(bOSFreePT)
{
pui32PDEntry[ui32PTIndex] = 0;
}
#endif
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
#if defined(PDUMP)
-
+ /* pdump the PD Page modifications */
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
#endif
@@ -676,7 +1097,7 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
-
+ /* advance to next context */
psMMUContext = psMMUContext->psNext;
}
break;
@@ -684,25 +1105,27 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
case DEVICE_MEMORY_HEAP_PERCONTEXT :
case DEVICE_MEMORY_HEAP_KERNEL :
{
-
+ MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+ /* Remove Page Table from this memory context only */
pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PD entry to the dummy PT */
pui32PDEntry[ui32PTIndex] = (pMMUHeap->psMMUContext->psDevInfo->sDummyPTDevPAddr.uiAddr
>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_VALID;
#else
-
+ /* free the entry */
if(bOSFreePT)
{
pui32PDEntry[ui32PTIndex] = 0;
}
#endif
+ MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
-
+ /* pdump the PD Page modifications */
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
break;
}
@@ -713,45 +1136,49 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
}
}
-
+ /* clear the PT entries in each PT page */
if(ppsPTInfoList[ui32PTIndex] != IMG_NULL)
{
if(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr != IMG_NULL)
{
IMG_PUINT32 pui32Tmp;
+ MakeKernelPageReadWrite(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr;
-
+ /* clear the entries */
for(i=0;
(i<pMMUHeap->ui32PTETotalUsable) && (i<pMMUHeap->ui32PTNumEntriesUsable);
i++)
{
-
+ /* over-allocated PT entries for 4MB data page case should never be non-zero */
pui32Tmp[i] = 0;
}
+ MakeKernelPageReadOnly(ppsPTInfoList[ui32PTIndex]->PTPageCpuVAddr);
-
-
+ /*
+ free the pagetable memory
+ */
if(bOSFreePT)
{
_FreePageTableMemory(pMMUHeap, ppsPTInfoList[ui32PTIndex]);
}
-
-
-
+ /*
+ decrement the PT Entry Count by the number
+ of entries we've cleared in this pass
+ */
pMMUHeap->ui32PTETotalUsable -= i;
}
else
{
-
+ /* decrement the PT Entry Count by a page's worth of entries */
pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
}
if(bOSFreePT)
{
-
+ /* free the pt info */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(MMU_PT_INFO),
ppsPTInfoList[ui32PTIndex],
@@ -761,13 +1188,22 @@ _DeferredFreePageTable (MMU_HEAP *pMMUHeap, IMG_UINT32 ui32PTIndex, IMG_BOOL bOS
}
else
{
-
+ /* decrement the PT Entry Count by a page's worth of usable entries */
pMMUHeap->ui32PTETotalUsable -= pMMUHeap->ui32PTNumEntriesUsable;
}
PDUMPCOMMENT("Finished free page table (page count == %08X)", pMMUHeap->ui32PageTableCount);
}
+/*!
+******************************************************************************
+ FUNCTION: _DeferredFreePageTables
+
+ PURPOSE: Free the page tables associated with an MMU.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
_DeferredFreePageTables (MMU_HEAP *pMMUHeap)
{
@@ -794,14 +1230,17 @@ _DeferredFreePageTables (MMU_HEAP *pMMUHeap)
{
if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
{
-
+ /*
+ * We have to do this to setup the dummy page as
+ * not all heaps are PD cache size or aligned
+ */
for (j=0;j<SGX_MMU_PT_SIZE;j++)
{
pui32Tmp = (IMG_UINT32 *) psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
BRN31620InvalidatePageTableEntry(psMMUContext, ui32PDIndex, j, &pui32Tmp[j]);
}
}
-
+ /* Free the PT and NULL's out the PTInfo */
if (BRN31620FreePageTable(pMMUHeap, ui32PDIndex) == IMG_TRUE)
{
bInvalidateDirectoryCache = IMG_TRUE;
@@ -809,7 +1248,10 @@ _DeferredFreePageTables (MMU_HEAP *pMMUHeap)
}
}
-
+ /*
+ * Due to freeing PT's in chunks we might need to flush the PT cache
+ * rather then the directory cache
+ */
if (bInvalidateDirectoryCache)
{
MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
@@ -828,6 +1270,18 @@ _DeferredFreePageTables (MMU_HEAP *pMMUHeap)
}
+/*!
+******************************************************************************
+ FUNCTION: _DeferredAllocPagetables
+
+ PURPOSE: allocates page tables at time of allocation
+
+ PARAMETERS: In: pMMUHeap - the mmu heap
+ DevVAddr - devVAddr of allocation
+ ui32Size - size of allocation
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failed
+******************************************************************************/
static IMG_BOOL
_DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
{
@@ -848,23 +1302,23 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
IMG_UINT32 ui32ModifiedCachelines[BRN31620_CACHE_FLUSH_INDEX_SIZE];
#endif
-
+ /* Check device linear address */
#if SGX_FEATURE_ADDRESS_SPACE_SIZE < 32
PVR_ASSERT(DevVAddr.uiAddr < (1<<SGX_FEATURE_ADDRESS_SPACE_SIZE));
#endif
-
+ /* get the sysdata */
SysAcquireData(&psSysData);
-
+ /* find the index/offset in PD entries */
ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
-
+ /* how many PDs does the allocation occupy? */
+ /* first check for overflows */
if((UINT32_MAX_VALUE - DevVAddr.uiAddr)
< (ui32Size + pMMUHeap->ui32DataPageMask + pMMUHeap->ui32PTMask))
{
-
+ /* detected overflow, clamp to highest address */
sHighDevVAddr.uiAddr = UINT32_MAX_VALUE;
}
else
@@ -877,7 +1331,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* Fix allocation of last 4MB */
if (ui32PageTableCount == 0)
ui32PageTableCount = 1024;
@@ -887,42 +1341,42 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
ui32ModifiedCachelines[i] = 0;
}
-
-
-
+ /*****************************************************************/
+ /* Save off requested data and round allocation to PD cache line */
+ /*****************************************************************/
sDevVAddrRequestStart = DevVAddr;
ui32PDRequestStart = ui32PDIndex;
sDevVAddrRequestEnd = sHighDevVAddr;
ui32PDRequestEnd = ui32PageTableCount - 1;
-
+ /* Round allocations down to the PD cacheline */
DevVAddr.uiAddr = DevVAddr.uiAddr & (~BRN31620_PDE_CACHE_FILL_MASK);
-
+ /* Round the end address of the PD allocation to cacheline */
sHighDevVAddr.uiAddr = ((sHighDevVAddr.uiAddr + (BRN31620_PDE_CACHE_FILL_SIZE - 1)) & (~BRN31620_PDE_CACHE_FILL_MASK));
ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
ui32PageTableCount = sHighDevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* Fix allocation of last 4MB */
if (ui32PageTableCount == 0)
ui32PageTableCount = 1024;
#endif
ui32PageTableCount -= ui32PDIndex;
-
+ /* get the PD CPUVAddr base and advance to the first entry */
pui32PDEntry = (IMG_UINT32*)pMMUHeap->psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
#if defined(PDUMP)
{
IMG_UINT32 ui32Flags = 0;
-
+ /* pdump the PD Page modifications */
if( MMU_IsHeapShared(pMMUHeap) )
{
ui32Flags |= PDUMP_FLAGS_CONTINUOUS;
@@ -935,16 +1389,16 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
PDUMPCOMMENTWITHFLAGS(ui32Flags, "Page directory mods (page count == %08X)", ui32PageTableCount);
}
#endif
-
+ /* walk the psPTInfoList to see what needs allocating: */
for(i=0; i<ui32PageTableCount; i++)
{
if(ppsPTInfoList[i] == IMG_NULL)
{
#if defined(FIX_HW_BRN_31620)
-
+ /* Check if we have a saved PT (i.e. this PDE cache line is still live) */
if (pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i])
{
-
+ /* Only make this PTInfo "live" if it's requested */
if (((ui32PDIndex + i) >= ui32PDRequestStart) && ((ui32PDIndex + i) <= ui32PDRequestEnd))
{
IMG_UINT32 ui32PDCacheLine = (ui32PDIndex + i) >> BRN31620_PDES_PER_CACHE_LINE_SHIFT;
@@ -973,7 +1427,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
#endif
}
#if defined(FIX_HW_BRN_31620)
-
+ /* Only try to allocate if ppsPTInfoList[i] is valid */
if (ppsPTInfoList[i])
{
#endif
@@ -986,7 +1440,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
IMG_UINT32 j;
#else
#if !defined(FIX_HW_BRN_31620)
-
+ /* no page table has been allocated so allocate one */
PVR_ASSERT(pui32PDEntry[i] == 0);
#endif
#endif
@@ -997,7 +1451,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
}
#if defined(FIX_HW_BRN_31620)
bFlushSystemCache = IMG_TRUE;
-
+ /* Bump up the page table count if required */
{
IMG_UINT32 ui32PD;
IMG_UINT32 ui32PDCacheLine;
@@ -1010,7 +1464,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
ui32PDBitMaskShift = ui32PDCacheLine & BRN31620_CACHE_FLUSH_BITS_MASK;
ui32ModifiedCachelines[ui32PDBitMaskIndex] |= 1 << ui32PDBitMaskShift;
-
+ /* Add 1 to ui32PD as we want the count, not a range */
if ((pMMUHeap->ui32PDBaseIndex + pMMUHeap->ui32PageTableCount) < (ui32PD + 1))
{
pMMUHeap->ui32PageTableCount = (ui32PD + 1) - pMMUHeap->ui32PDBaseIndex;
@@ -1027,30 +1481,32 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
case DEVICE_MEMORY_HEAP_SHARED :
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED :
{
-
+ /* insert Page Table into all memory contexts */
MMU_CONTEXT *psMMUContext = (MMU_CONTEXT*)pMMUHeap->psMMUContext->psDevInfo->pvMMUContextList;
while(psMMUContext)
{
-
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ /* get the PD CPUVAddr base and advance to the first entry */
pui32PDEntry = (IMG_UINT32*)psMMUContext->pvPDCpuVAddr;
pui32PDEntry += ui32PDIndex;
-
+ /* insert the page, specify the data page size and make the pde valid */
pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| pMMUHeap->ui32PDEPageSizeCtrl
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
#if defined(PDUMP)
-
+ /* pdump the PD Page modifications */
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
#endif
{
-
+ //PDUMPCOMMENT("_DeferredAllocPTs: Dumping shared PDEs on context %d (%s)", psMMUContext->ui32PDumpMMUContextID, (psMMUContext->bPDumpActive) ? "active" : "");
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
- #endif
-
+ #endif /* PDUMP */
+ /* advance to next context */
psMMUContext = psMMUContext->psNext;
}
#if defined(FIX_HW_BRN_31620)
@@ -1061,13 +1517,14 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
case DEVICE_MEMORY_HEAP_PERCONTEXT :
case DEVICE_MEMORY_HEAP_KERNEL :
{
-
+ MakeKernelPageReadWrite(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+ /* insert Page Table into only this memory context */
pui32PDEntry[i] = (sDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| pMMUHeap->ui32PDEPageSizeCtrl
| SGX_MMU_PDE_VALID;
-
-
-
+ MakeKernelPageReadOnly(pMMUHeap->psMMUContext->pvPDCpuVAddr);
+ /* pdump the PD Page modifications */
+ //PDUMPCOMMENT("_DeferredAllocPTs: Dumping kernel PDEs on context %d (%s)", pMMUHeap->psMMUContext->ui32PDumpMMUContextID, (pMMUHeap->psMMUContext->bPDumpActive) ? "active" : "");
PDUMPPDENTRIES(&pMMUHeap->sMMUAttrib, pMMUHeap->psMMUContext->hPDOSMemHandle, (IMG_VOID*)&pui32PDEntry[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
break;
}
@@ -1079,14 +1536,15 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
}
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
-
-
-
-
+ /* This is actually not to do with multiple mem contexts, but to do with the directory cache.
+ In the 1 context implementation of the MMU, the directory "cache" is actually a copy of the
+ page directory memory, and requires updating whenever the page directory changes, even if there
+ was no previous value in a particular entry
+ */
MMU_InvalidateDirectoryCache(pMMUHeap->psMMUContext->psDevInfo);
#endif
#if defined(FIX_HW_BRN_31620)
-
+ /* If this PT is not in the requested range then save it and null out the main PTInfo */
if (((ui32PDIndex + i) < ui32PDRequestStart) || ((ui32PDIndex + i) > ui32PDRequestEnd))
{
pMMUHeap->psMMUContext->apsPTInfoListSave[ui32PDIndex + i] = ppsPTInfoList[i];
@@ -1097,7 +1555,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
else
{
#if !defined(FIX_HW_BRN_31620)
-
+ /* already have an allocated PT */
PVR_ASSERT(pui32PDEntry[i] != 0);
#endif
}
@@ -1108,20 +1566,20 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
#if defined(SGX_FEATURE_SYSTEM_CACHE)
#if defined(FIX_HW_BRN_31620)
-
+ /* This function might not allocate any new PT's so check before flushing */
if (bFlushSystemCache)
{
#endif
MMU_InvalidateSystemLevelCache(pMMUHeap->psMMUContext->psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
#if defined(FIX_HW_BRN_31620)
}
-
+ /* Handle the last 4MB roll over */
sHighDevVAddr.uiAddr = sHighDevVAddr.uiAddr - 1;
-
+ /* Update our PD flush mask if required */
if (bFlushSystemCache)
{
MMU_CONTEXT *psMMUContext;
@@ -1137,7 +1595,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
psMMUContext->ui32PDChangeMask[i] |= ui32ModifiedCachelines[i];
}
-
+ /* advance to next context */
psMMUContext = psMMUContext->psNext;
}
}
@@ -1149,7 +1607,11 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
}
}
-
+ /*
+ * Always hook up the dummy page when we allocate a new range of PTs.
+ * It might be this is overwritten before the SGX access the dummy page
+ * but we don't care, it's a lot simpler to add this logic here.
+ */
psMMUContext = pMMUHeap->psMMUContext;
for (i=0;i<BRN31620_CACHE_FLUSH_INDEX_SIZE;i++)
{
@@ -1165,7 +1627,7 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
ui32PDIndex = (((i * BRN31620_CACHE_FLUSH_BITS_SIZE) + j) * BRN31620_PDES_PER_CACHE_LINE_SIZE) + BRN31620_DUMMY_PDE_INDEX;
-
+ /* The PT for the dummy page might not be "live". If not get it from the saved pointer */
if (psMMUContext->apsPTInfoList[ui32PDIndex])
{
psTempPTInfo = psMMUContext->apsPTInfoList[ui32PDIndex];
@@ -1177,13 +1639,14 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
PVR_ASSERT(psTempPTInfo != IMG_NULL);
+ MakeKernelPageReadWrite(psTempPTInfo->PTPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *) psTempPTInfo->PTPageCpuVAddr;
PVR_ASSERT(pui32Tmp != IMG_NULL);
pui32Tmp[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_DUMMY_PAGE
| SGX_MMU_PTE_READONLY
| SGX_MMU_PTE_VALID;
-
+ MakeKernelPageReadOnly(psTempPTInfo->PTPageCpuVAddr);
PDUMPCOMMENT("BRN31620 Dump PTE for dummy page after wireing up new PT");
PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psTempPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32Tmp[BRN31620_DUMMY_PTE_INDEX], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
@@ -1197,20 +1660,44 @@ _DeferredAllocPagetables(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT
#if defined(PDUMP)
+/*!
+ * FUNCTION: MMU_GetPDumpContextID
+ *
+ * RETURNS: pdump MMU context ID
+ */
IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext)
{
BM_CONTEXT *pBMContext = hDevMemContext;
PVR_ASSERT(pBMContext);
-
+ /* PRQA S 0505 1 */ /* PVR_ASSERT should catch NULL ptr */
return pBMContext->psMMUContext->ui32PDumpMMUContextID;
}
+/*!
+ * FUNCTION: MMU_SetPDumpAttribs
+ *
+ * PURPOSE: Called from MMU_Initialise and MMU_Create.
+ * Sets up device-specific attributes for pdumping.
+ * FIXME: breaks variable size PTs. Really need separate per context
+ * and per heap attribs.
+ *
+ * INPUT: psDeviceNode - used to access deviceID
+ * INPUT: ui32DataPageMask - data page mask
+ * INPUT: ui32PTSize - PT size
+ *
+ * OUTPUT: psMMUAttrib - pdump MMU attributes
+ *
+ * RETURNS: none
+ */
+#if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE)
+# error "FIXME: breaks variable size pagetables"
+#endif
static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32DataPageMask,
IMG_UINT32 ui32PTSize)
{
-
+ /* Sets up device ID, contains pdump memspace name */
psMMUAttrib->sDevId = psDeviceNode->sDevId;
psMMUAttrib->pszPDRegRegion = IMG_NULL;
@@ -1223,8 +1710,18 @@ static IMG_VOID MMU_SetPDumpAttribs(PDUMP_MMU_ATTRIB *psMMUAttrib,
psMMUAttrib->ui32PDEMask = SGX_MMU_PDE_ADDR_MASK;
psMMUAttrib->ui32PDEAlignShift = SGX_MMU_PDE_ADDR_ALIGNSHIFT;
}
-#endif
+#endif /* PDUMP */
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_Initialise
+
+ PURPOSE: Called from BM_CreateContext.
+ Allocates the top level Page Directory 4k Page for the new context.
+ PARAMETERS: None
+ RETURNS: PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR
MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr)
{
@@ -1244,8 +1741,8 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
SysAcquireData(&psSysData);
#if defined(PDUMP)
-
-
+ /* Note: these attribs are on the stack, used only to pdump the MMU context
+ * creation. */
MMU_SetPDumpAttribs(&sMMUAttrib, psDeviceNode,
SGX_MMU_PAGE_MASK,
SGX_MMU_PT_SIZE * sizeof(IMG_UINT32));
@@ -1262,21 +1759,24 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
}
OSMemSet (psMMUContext, 0, sizeof(MMU_CONTEXT));
-
+ /* stick the devinfo in the context for subsequent use */
psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
psMMUContext->psDevInfo = psDevInfo;
-
+ /* record device node for subsequent use */
psMMUContext->psDeviceNode = psDeviceNode;
-
+ /* allocate 4k page directory page for the new context */
if(psDeviceNode->psLocalDevMemArena == IMG_NULL)
{
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &pvPDCpuVAddr,
- &hPDOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &pvPDCpuVAddr,
+ &hPDOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
@@ -1289,7 +1789,8 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
}
else
{
-
+ /* This is not used in all cases, since not all ports currently
+ * support OSMemHandleToCpuPAddr */
sCpuPAddr = OSMemHandleToCpuPAddr(hPDOSMemHandle, 0);
}
sPDDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
@@ -1299,15 +1800,18 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* Allocate dummy PT and Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
-
+ /* Dummy PT page */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvDummyPTPageCpuVAddr,
- &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvDummyPTPageCpuVAddr,
+ &psDevInfo->hDummyPTPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
@@ -1320,17 +1824,21 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
}
else
{
-
+ /* This is not used in all cases, since not all ports currently
+ * support OSMemHandleToCpuPAddr */
sCpuPAddr = OSMemHandleToCpuPAddr(psDevInfo->hDummyPTPageOSMemHandle, 0);
}
psDevInfo->sDummyPTDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
+ /* Dummy Data page */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvDummyDataPageCpuVAddr,
- &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvDummyDataPageCpuVAddr,
+ &psDevInfo->hDummyDataPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
@@ -1347,24 +1855,27 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
}
psDevInfo->sDummyDataDevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
}
-#endif
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
#if defined(FIX_HW_BRN_31620)
-
+ /* Allocate dummy Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
IMG_UINT32 j;
-
+ /* Allocate dummy page */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvBRN31620DummyPageCpuVAddr,
- &psDevInfo->hBRN31620DummyPageOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvBRN31620DummyPageCpuVAddr,
+ &psDevInfo->hBRN31620DummyPageOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
-
+ /* Get a physical address */
if(psDevInfo->pvBRN31620DummyPageCpuVAddr)
{
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
@@ -1384,18 +1895,21 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
psDevInfo->sBRN31620DummyPageDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
-
+ /* Allocate dummy PT */
if (OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- &psDevInfo->pvBRN31620DummyPTCpuVAddr,
- &psDevInfo->hBRN31620DummyPTOSMemHandle) != PVRSRV_OK)
+ SGX_MMU_PAGE_SIZE,
+ SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
+ &psDevInfo->pvBRN31620DummyPTCpuVAddr,
+ &psDevInfo->hBRN31620DummyPTOSMemHandle) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to OSAllocPages failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_PAGES;
}
-
+ /* Get a physical address */
if(psDevInfo->pvBRN31620DummyPTCpuVAddr)
{
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
@@ -1416,7 +1930,7 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
{
IMG_SYS_PHYADDR sSysPAddr;
-
+ /* allocate from the device's local memory arena */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
@@ -1424,13 +1938,15 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
sPDDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
pvPDCpuVAddr = OSMapPhysToLin(sCpuPAddr,
@@ -1448,10 +1964,10 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* Allocate dummy PT and Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
-
+ /* Dummy PT page */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
@@ -1459,13 +1975,15 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sDummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvDummyPTPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
@@ -1478,7 +1996,7 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
}
-
+ /* Dummy Data page */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
@@ -1486,13 +2004,15 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sDummyDataDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvDummyDataPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
@@ -1505,13 +2025,13 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
}
}
-#endif
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
#if defined(FIX_HW_BRN_31620)
-
+ /* Allocate dummy PT and Data pages for the first context to be created */
if(!psDevInfo->pvMMUContextList)
{
IMG_UINT32 j;
-
+ /* Allocate dummy page */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
@@ -1519,13 +2039,15 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sBRN31620DummyPageDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvBRN31620DummyPageCpuVAddr = OSMapPhysToLin(sCpuPAddr,
@@ -1538,14 +2060,16 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
return PVRSRV_ERROR_FAILED_TO_MAP_PAGE_TABLE;
}
+ MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *)psDevInfo->pvBRN31620DummyPageCpuVAddr;
for(j=0; j<(SGX_MMU_PAGE_SIZE/4); j++)
{
pui32Tmp[j] = BRN31620_DUMMY_PAGE_SIGNATURE;
}
+ MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPageCpuVAddr);
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, 0, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
-
+ /* Allocate dummy PT */
if(RA_Alloc(psDeviceNode->psLocalDevMemArena,
SGX_MMU_PAGE_SIZE,
IMG_NULL,
@@ -1553,13 +2077,15 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sSysPAddr.uiAddr))!= IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_FAILED_TO_ALLOC_VIRT_MEMORY;
}
-
+ /* derive the CPU virtual address */
sCpuPAddr = SysSysPAddrToCpuPAddr(sSysPAddr);
psDevInfo->sBRN31620DummyPTDevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysPAddr);
psDevInfo->pvBRN31620DummyPTCpuVAddr = OSMapPhysToLin(sCpuPAddr,
@@ -1576,13 +2102,13 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
OSMemSet(psDevInfo->pvBRN31620DummyPTCpuVAddr,0,SGX_MMU_PAGE_SIZE);
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, 0, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
}
-#endif
+#endif /* #if defined(FIX_HW_BRN_31620) */
}
#if defined(FIX_HW_BRN_31620)
if (!psDevInfo->pvMMUContextList)
{
-
+ /* Save the kernel MMU context which is always the 1st to be created */
psDevInfo->hKernelMMUContext = psMMUContext;
PVR_DPF((PVR_DBG_ERROR, "MMU_Initialise: saving kernel mmu context: %p", psMMUContext));
}
@@ -1590,12 +2116,14 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
#if defined(PDUMP)
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* Find out if this context is for the active pdump client.
+ * If it is, need to ensure PD entries are pdumped whenever another
+ * process allocates from a shared heap. */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc == IMG_NULL)
{
-
+ /* changes to the kernel context PD/PTs should be pdumped */
psMMUContext->bPDumpActive = IMG_TRUE;
}
else
@@ -1603,8 +2131,8 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
psMMUContext->bPDumpActive = psPerProc->bPDumpActive;
}
}
-#endif
-
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
+ /* pdump the PD malloc */
#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
PDUMPCOMMENT("Alloc page directory for new MMU context (PDDevPAddr == 0x%08x)",
sPDDevPAddr.uiAddr);
@@ -1613,7 +2141,7 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
sPDDevPAddr.uiHighAddr, sPDDevPAddr.uiAddr);
#endif
PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDOSMemHandle, 0, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
-#endif
+#endif /* PDUMP */
#ifdef SUPPORT_SGX_MMU_BYPASS
EnableHostAccess(psMMUContext);
@@ -1631,55 +2159,65 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
+ /* wire-up the new PD to the dummy PT */
for(i=0; i<SGX_MMU_PD_SIZE; i++)
{
pui32Tmp[i] = (psDevInfo->sDummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_VALID;
}
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
if(!psDevInfo->pvMMUContextList)
{
-
-
-
+ /*
+ if we've just allocated the dummy pages
+ wire up the dummy PT to the dummy data page
+ */
+ MakeKernelPageReadWrite(psDevInfo->pvDummyPTPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyPTPageCpuVAddr;
for(i=0; i<SGX_MMU_PT_SIZE; i++)
{
pui32Tmp[i] = (psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
}
-
+ MakeKernelPageReadOnly(psDevInfo->pvDummyPTPageCpuVAddr);
+ /* pdump the Dummy PT Page */
PDUMPCOMMENT("Dummy Page table contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hDummyPTOSMemHandle, psDevInfo->pvDummyPTPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
-
-
+ /*
+ write a signature to the dummy data page
+ */
+ MakeKernelPageReadWrite(psDevInfo->pvDummyDataPageCpuVAddr);
pui32Tmp = (IMG_UINT32 *)psDevInfo->pvDummyDataPageCpuVAddr;
for(i=0; i<(SGX_MMU_PAGE_SIZE/4); i++)
{
pui32Tmp[i] = DUMMY_DATA_PAGE_SIGNATURE;
}
-
+ MakeKernelPageReadOnly(psDevInfo->pvDummyDataPageCpuVAddr);
+ /* pdump the Dummy Data Page */
PDUMPCOMMENT("Dummy Data Page contents");
PDUMPMEMPTENTRIES(PVRSRV_DEVICE_TYPE_SGX, psDevInfo->hDummyDataPageOSMemHandle, psDevInfo->pvDummyDataPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
-#else
-
+#else /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
+ /* initialise the PD to invalid address state */
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
for(i=0; i<SGX_MMU_PD_SIZE; i++)
{
-
+ /* invalid, no read, no write, no cache consistency */
pui32Tmp[i] = 0;
}
-#endif
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
+#endif /* #if defined(SUPPORT_SGX_MMU_DUMMY_PAGE) */
#if defined(PDUMP)
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
{
-
+ /* pdump the PD Page */
PDUMPCOMMENT("Page directory contents");
PDUMPPDENTRIES(&sMMUAttrib, hPDOSMemHandle, pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
@@ -1693,59 +2231,62 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
PDUMPCOMMENT("BRN31620 Set up dummy PT");
+ MakeKernelPageReadWrite(psDevInfo->pvBRN31620DummyPTCpuVAddr);
pui32PT = (IMG_UINT32 *) psDevInfo->pvBRN31620DummyPTCpuVAddr;
pui32PT[BRN31620_DUMMY_PTE_INDEX] = (psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_DUMMY_PAGE
| SGX_MMU_PTE_READONLY
| SGX_MMU_PTE_VALID;
-
+ MakeKernelPageReadOnly(psDevInfo->pvBRN31620DummyPTCpuVAddr);
#if defined(PDUMP)
-
+ /* Dump initial contents */
PDUMPCOMMENT("BRN31620 Dump dummy PT contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
PDUMPCOMMENT("BRN31620 Dump dummy page contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
-
+ /* Dump the wiring */
for(i=0;i<SGX_MMU_PT_SIZE;i++)
{
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPTOSMemHandle, &pui32PT[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
PDUMPCOMMENT("BRN31620 Dump PDE wire up");
-
+ /* Walk the PD wireing up the PT's */
for(i=0;i<SGX_MMU_PD_SIZE;i++)
{
pui32Tmp[i] = 0;
if (ui32PDCount == BRN31620_DUMMY_PDE_INDEX)
{
+ MakeKernelPageReadWrite(pvPDCpuVAddr);
pui32Tmp[i] = (psDevInfo->sBRN31620DummyPTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
| SGX_MMU_PDE_DUMMY_PAGE
| SGX_MMU_PDE_VALID;
+ MakeKernelPageReadOnly(pvPDCpuVAddr);
}
PDUMPMEMPTENTRIES(&sMMUAttrib, hPDOSMemHandle, (IMG_VOID *) &pui32Tmp[i], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PT_UNIQUETAG);
ui32PDCount++;
if (ui32PDCount == BRN31620_PDES_PER_CACHE_LINE_SIZE)
{
-
+ /* Reset PT count */
ui32PDCount = 0;
}
}
-
+ /* pdump the Dummy PT Page */
PDUMPCOMMENT("BRN31620 dummy Page table contents");
PDUMPMEMPTENTRIES(&sMMUAttrib, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
#endif
#if defined(PDUMP)
-
+ /* pdump set MMU context */
{
PVRSRV_ERROR eError;
-
+ /* default MMU type is 1, 4k page */
IMG_UINT32 ui32MMUType = 1;
#if defined(SGX_FEATURE_36BIT_MMU)
@@ -1770,7 +2311,7 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
}
}
-
+ /* PDump the context ID */
PDUMPCOMMENT("Set MMU context complete (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
#endif
@@ -1790,18 +2331,24 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
psMMUContext->apsPTInfoListSave[i] = IMG_NULL;
}
#endif
-
+ /* store PD info in the MMU context */
psMMUContext->pvPDCpuVAddr = pvPDCpuVAddr;
psMMUContext->sPDDevPAddr = sPDDevPAddr;
psMMUContext->hPDOSMemHandle = hPDOSMemHandle;
-
+ /* Get some process information to aid debug */
+ psMMUContext->ui32PID = OSGetCurrentProcessIDKM();
+ psMMUContext->szName[0] = '\0';
+ OSGetCurrentProcessNameKM(psMMUContext->szName, MMU_CONTEXT_NAME_SIZE);
+
+ /* return context */
*ppsMMUContext = psMMUContext;
-
+ /* return the PD DevVAddr */
*psPDDevPAddr = sPDDevPAddr;
-
+
+ /* add the new MMU context onto the list of MMU contexts */
psMMUContext->psNext = (MMU_CONTEXT*)psDevInfo->pvMMUContextList;
psDevInfo->pvMMUContextList = (IMG_VOID*)psMMUContext;
@@ -1812,6 +2359,15 @@ MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, I
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Finalise
+
+ PURPOSE: Finalise the mmu module, deallocate all resources.
+
+ PARAMETERS: In: psMMUContext - MMU context to deallocate
+ RETURNS: None.
+******************************************************************************/
IMG_VOID
MMU_Finalise (MMU_CONTEXT *psMMUContext)
{
@@ -1826,11 +2382,11 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext)
SysAcquireData(&psSysData);
#if defined(PDUMP)
-
+ /* pdump the MMU context clear */
PDUMPCOMMENT("Clear MMU context (MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
PDUMPCLEARMMUCONTEXT(PVRSRV_DEVICE_TYPE_SGX, psMMUContext->psDeviceNode->sDevId.pszPDumpDevName, psMMUContext->ui32PDumpMMUContextID, 2);
-
+ /* pdump the PD free */
#if IMG_ADDRSPACE_PHYSADDR_BITS == 32
PDUMPCOMMENT("Free page directory (PDDevPAddr == 0x%08x)",
psMMUContext->sPDDevPAddr.uiAddr);
@@ -1838,7 +2394,7 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext)
PDUMPCOMMENT("Free page directory, 64-bit arch detected (PDDevPAddr == 0x%08x%08x)",
psMMUContext->sPDDevPAddr.uiHighAddr, psMMUContext->sPDDevPAddr.uiAddr);
#endif
-#endif
+#endif /* PDUMP */
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psMMUContext->hPDOSMemHandle, psMMUContext->pvPDCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
@@ -1848,29 +2404,33 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext)
pui32Tmp = (IMG_UINT32 *)psMMUContext->pvPDCpuVAddr;
-
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ /* initialise the PD to invalid address state */
for(i=0; i<SGX_MMU_PD_SIZE; i++)
{
-
+ /* invalid, no read, no write, no cache consistency */
pui32Tmp[i] = 0;
}
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
-
-
-
-
+ /*
+ free the PD:
+ depending on the specific system, the PD is allocated from system memory
+ or device local memory. For now, just look for at least a valid local heap/arena
+ */
if(psMMUContext->psDeviceNode->psLocalDevMemArena == IMG_NULL)
{
#if defined(FIX_HW_BRN_31620)
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psMMUContext->psDevInfo;
#endif
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
SGX_MMU_PAGE_SIZE,
psMMUContext->pvPDCpuVAddr,
psMMUContext->hPDOSMemHandle);
#if defined(FIX_HW_BRN_31620)
-
+ /* If this is the _last_ MMU context it must be the uKernel */
if (!psMMUContextList->psNext)
{
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
@@ -1888,7 +2448,7 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext)
}
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* if this is the last context free the dummy pages too */
if(!psMMUContextList->psNext)
{
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
@@ -1907,82 +2467,82 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext)
IMG_SYS_PHYADDR sSysPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
-
+ /* derive the system physical address */
sCpuPAddr = OSMapLinToCPUPhys(psMMUContext->hPDOSMemHandle,
psMMUContext->pvPDCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psMMUContext->pvPDCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psMMUContext->hPDOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* if this is the last context free the dummy pages too */
if(!psMMUContextList->psNext)
{
-
+ /* free the Dummy PT Page */
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyPTPageOSMemHandle,
psDevInfo->pvDummyPTPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvDummyPTPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hDummyPTPageOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
-
+ /* free the Dummy Data Page */
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hDummyDataPageOSMemHandle,
psDevInfo->pvDummyDataPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvDummyDataPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hDummyDataPageOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
}
#endif
#if defined(FIX_HW_BRN_31620)
-
+ /* if this is the last context free the dummy pages too */
if(!psMMUContextList->psNext)
{
-
+ /* free the Page */
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPageOSMemHandle, psDevInfo->pvBRN31620DummyPageCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPageOSMemHandle,
psDevInfo->pvBRN31620DummyPageCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPageCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hBRN31620DummyPageOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
-
+ /* free the Dummy PT */
PDUMPFREEPAGETABLE(&psMMUContext->psDeviceNode->sDevId, psDevInfo->hBRN31620DummyPTOSMemHandle, psDevInfo->pvBRN31620DummyPTCpuVAddr, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
sCpuPAddr = OSMapLinToCPUPhys(psDevInfo->hBRN31620DummyPTOSMemHandle,
psDevInfo->pvBRN31620DummyPTCpuVAddr);
sSysPAddr = SysCpuPAddrToSysPAddr(sCpuPAddr);
-
+ /* unmap the CPU mapping */
OSUnMapPhysToLin(psDevInfo->pvBRN31620DummyPTCpuVAddr,
SGX_MMU_PAGE_SIZE,
PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
psDevInfo->hBRN31620DummyPTOSMemHandle);
-
+ /* and free the memory */
RA_Free (psMMUContext->psDeviceNode->psLocalDevMemArena, sSysPAddr.uiAddr, IMG_FALSE);
}
#endif
@@ -1990,27 +2550,38 @@ MMU_Finalise (MMU_CONTEXT *psMMUContext)
PVR_DPF ((PVR_DBG_MESSAGE, "MMU_Finalise"));
-
+ /* remove the MMU context from the list of MMU contexts */
ppsMMUContext = (MMU_CONTEXT**)&psMMUContext->psDevInfo->pvMMUContextList;
while(*ppsMMUContext)
{
if(*ppsMMUContext == psMMUContext)
{
-
+ /* remove item from the list */
*ppsMMUContext = psMMUContext->psNext;
break;
}
-
+ /* advance to next next */
ppsMMUContext = &((*ppsMMUContext)->psNext);
}
-
+ /* free the context itself. */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_CONTEXT), psMMUContext, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_InsertHeap
+
+ PURPOSE: Copies PDEs from shared/exported heap into current MMU context.
+
+ PARAMETERS: In: psMMUContext - the mmu
+ In: psMMUHeap - a shared/exported heap
+
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
{
@@ -2021,20 +2592,21 @@ MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
IMG_BOOL bInvalidateDirectoryCache = IMG_FALSE;
#endif
-
+ /* advance to the first entry */
pui32PDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
pui32KernelPDCpuVAddr += psMMUHeap->psDevArena->BaseDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
-
-
-
+ /*
+ update the PD range relating to the heap's
+ device virtual address range
+ */
#if defined(PDUMP)
PDUMPCOMMENT("Page directory shared heap range copy");
PDUMPCOMMENT(" (Source heap MMU Context ID == %u, PT count == 0x%x)",
psMMUHeap->psMMUContext->ui32PDumpMMUContextID,
psMMUHeap->ui32PageTableCount);
PDUMPCOMMENT(" (Destination MMU Context ID == %u)", psMMUContext->ui32PDumpMMUContextID);
-#endif
+#endif /* PDUMP */
#ifdef SUPPORT_SGX_MMU_BYPASS
EnableHostAccess(psMMUContext);
#endif
@@ -2042,20 +2614,29 @@ MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
for (ui32PDEntry = 0; ui32PDEntry < psMMUHeap->ui32PageTableCount; ui32PDEntry++)
{
#if (!defined(SUPPORT_SGX_MMU_DUMMY_PAGE)) && (!defined(FIX_HW_BRN_31620))
-
+ /* check we have invalidated target PDEs */
PVR_ASSERT(pui32PDCpuVAddr[ui32PDEntry] == 0);
#endif
-
-
+ MakeKernelPageReadWrite(psMMUContext->pvPDCpuVAddr);
+ /* copy over the PDEs */
pui32PDCpuVAddr[ui32PDEntry] = pui32KernelPDCpuVAddr[ui32PDEntry];
+ MakeKernelPageReadOnly(psMMUContext->pvPDCpuVAddr);
if (pui32PDCpuVAddr[ui32PDEntry])
{
-
+ /* Ensure the shared heap allocation is mapped into the context/PD
+ * for the active pdump process/app. The PTs and backing physical
+ * should also be pdumped (elsewhere).
+ * MALLOC (PT)
+ * LDB (init PT)
+ * MALLOC (data page)
+ * WRW (PTE->data page)
+ * LDB (init data page) -- could be useful to ensure page is initialised
+ */
#if defined(PDUMP)
-
+ //PDUMPCOMMENT("MMU_InsertHeap: Mapping shared heap to new context %d (%s)", psMMUContext->ui32PDumpMMUContextID, (psMMUContext->bPDumpActive) ? "active" : "");
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
if(psMMUContext->bPDumpActive)
- #endif
+ #endif /* SUPPORT_PDUMP_MULTI_PROCESS */
{
PDUMPPDENTRIES(&psMMUHeap->sMMUAttrib, psMMUContext->hPDOSMemHandle, (IMG_VOID *) &pui32PDCpuVAddr[ui32PDEntry], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
}
@@ -2073,16 +2654,30 @@ MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap)
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
if (bInvalidateDirectoryCache)
{
-
-
-
-
+ /* This is actually not to do with multiple mem contexts, but to do with the directory cache.
+ In the 1 context implementation of the MMU, the directory "cache" is actually a copy of the
+ page directory memory, and requires updating whenever the page directory changes, even if there
+ was no previous value in a particular entry
+ */
MMU_InvalidateDirectoryCache(psMMUContext->psDevInfo);
}
#endif
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_UnmapPagesAndFreePTs
+
+ PURPOSE: unmap pages, invalidate virtual address and try to free the PTs
+
+ PARAMETERS: In: psMMUHeap - the mmu.
+ In: sDevVAddr - the device virtual address.
+ In: ui32PageCount - page count
+ In: hUniqueTag - A unique ID for use as a tag identifier
+
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
IMG_DEV_VIRTADDR sDevVAddr,
@@ -2099,39 +2694,48 @@ MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
#if !defined (PDUMP)
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
#endif
-
+ /* setup tmp devvaddr to base of allocation */
sTmpDevVAddr = sDevVAddr;
for(i=0; i<ui32PageCount; i++)
{
MMU_PT_INFO **ppsPTInfoList;
-
+ /* find the index/offset in PD entries */
ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
{
-
+ /* find the index/offset of the first PT in the first PT page */
ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
-
+ /* Is the PT page valid? */
if (!ppsPTInfoList[0])
{
- PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ /*
+ With sparse mappings we expect that the PT could be freed
+ before we reach the end of it as the unmapped pages don't
+ bump ui32ValidPTECount so it can reach zero before we reach
+ the end of the PT.
+ */
+ if (!psMMUHeap->bHasSparseMappings)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
-
+ /* Try to unmap the remaining allocation pages */
continue;
}
-
+ /* setup pointer to the first entry in the PT page */
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
-
+ /* Is PTPageCpuVAddr valid ? */
if (!pui32Tmp)
{
continue;
@@ -2139,37 +2743,41 @@ MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
CheckPT(ppsPTInfoList[0]);
-
+ /* Decrement the valid page count only if the current page is valid*/
if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
{
ppsPTInfoList[0]->ui32ValidPTECount--;
}
else
{
- PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ if (!psMMUHeap->bHasSparseMappings)
+ {
+ PVR_DPF((PVR_DBG_MESSAGE, "MMU_UnmapPagesAndFreePTs: Page is already invalid for alloc at VAddr:0x%08X (VAddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",sTmpDevVAddr.uiAddr, sDevVAddr.uiAddr,i, ui32PDIndex, ui32PTIndex ));
+ }
}
-
+ /* The page table count should not go below zero */
PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
-
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PT entry to the dummy data page */
pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
#else
-
+ /* invalidate entry */
#if defined(FIX_HW_BRN_31620)
BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
#else
pui32Tmp[ui32PTIndex] = 0;
#endif
#endif
-
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
CheckPT(ppsPTInfoList[0]);
}
-
-
+ /*
+ Free a page table if we can.
+ */
if (ppsPTInfoList[0] && (ppsPTInfoList[0]->ui32ValidPTECount == 0)
)
{
@@ -2184,7 +2792,7 @@ MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
#endif
}
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += psMMUHeap->ui32DataPageSize;
}
@@ -2203,10 +2811,23 @@ MMU_UnmapPagesAndFreePTs (MMU_HEAP *psMMUHeap,
psMMUHeap->ui32DataPageSize * ui32PageCount,
IMG_TRUE,
hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_FreePageTables
+
+ PURPOSE: Call back from RA_Free to zero page table entries used by freed
+ spans.
+
+ PARAMETERS: In: pvMMUHeap
+ In: ui32Start
+ In: ui32End
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS:
+******************************************************************************/
static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
IMG_SIZE_T ui32Start,
IMG_SIZE_T ui32End,
@@ -2220,6 +2841,18 @@ static IMG_VOID MMU_FreePageTables(IMG_PVOID pvMMUHeap,
MMU_UnmapPagesAndFreePTs(pMMUHeap, Start, (IMG_UINT32)((ui32End - ui32Start) >> pMMUHeap->ui32PTShift), hUniqueTag);
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Create
+
+ PURPOSE: Create an mmu device virtual heap.
+
+ PARAMETERS: In: psMMUContext - MMU context
+ In: psDevArena - device memory resource arena
+ Out: ppsVMArena - virtual mapping arena
+ RETURNS: MMU_HEAP
+ RETURNS:
+******************************************************************************/
MMU_HEAP *
MMU_Create (MMU_CONTEXT *psMMUContext,
DEV_ARENA_DESCRIPTOR *psDevArena,
@@ -2252,9 +2885,10 @@ MMU_Create (MMU_CONTEXT *psMMUContext,
pMMUHeap->psMMUContext = psMMUContext;
pMMUHeap->psDevArena = psDevArena;
-
-
-
+ /*
+ generate page table and data page mask and shift values
+ based on the data page size
+ */
switch(pMMUHeap->psDevArena->ui32DataPageSize)
{
case 0x1000:
@@ -2282,67 +2916,72 @@ MMU_Create (MMU_CONTEXT *psMMUContext,
ui32ScaleSize = 10;
pMMUHeap->ui32PDEPageSizeCtrl = SGX_MMU_PDE_PAGE_SIZE_4M;
break;
-#endif
+#endif /* #if defined(SGX_FEATURE_VARIABLE_MMU_PAGE_SIZE) */
default:
PVR_DPF((PVR_DBG_ERROR, "MMU_Create: invalid data page size"));
goto ErrorFreeHeap;
}
-
+ /* number of bits of address offset into the data page */
pMMUHeap->ui32DataPageSize = psDevArena->ui32DataPageSize;
pMMUHeap->ui32DataPageBitWidth = SGX_MMU_PAGE_SHIFT + ui32ScaleSize;
pMMUHeap->ui32DataPageMask = pMMUHeap->ui32DataPageSize - 1;
-
+ /* number of bits of address indexing into a pagetable */
pMMUHeap->ui32PTShift = pMMUHeap->ui32DataPageBitWidth;
pMMUHeap->ui32PTBitWidth = SGX_MMU_PT_SHIFT - ui32ScaleSize;
pMMUHeap->ui32PTMask = SGX_MMU_PT_MASK & (SGX_MMU_PT_MASK<<ui32ScaleSize);
pMMUHeap->ui32PTSize = (IMG_UINT32)(1UL<<pMMUHeap->ui32PTBitWidth) * sizeof(IMG_UINT32);
-
+ /* note: PT size must be at least 4 entries, even for 4Mb data page size */
if(pMMUHeap->ui32PTSize < 4 * sizeof(IMG_UINT32))
{
pMMUHeap->ui32PTSize = 4 * sizeof(IMG_UINT32);
}
pMMUHeap->ui32PTNumEntriesAllocated = pMMUHeap->ui32PTSize >> 2;
-
+ /* find the number of actual PT entries per PD entry range. For 4MB data
+ * pages we only use the first entry although the PT has 16 byte allocation/alignment
+ * (due to 4 LSbits of the PDE are reserved for control) */
pMMUHeap->ui32PTNumEntriesUsable = (IMG_UINT32)(1UL << pMMUHeap->ui32PTBitWidth);
-
+ /* number of bits of address indexing into a page directory */
pMMUHeap->ui32PDShift = pMMUHeap->ui32PTBitWidth + pMMUHeap->ui32PTShift;
pMMUHeap->ui32PDBitWidth = SGX_FEATURE_ADDRESS_SPACE_SIZE - pMMUHeap->ui32PTBitWidth - pMMUHeap->ui32DataPageBitWidth;
pMMUHeap->ui32PDMask = SGX_MMU_PD_MASK & (SGX_MMU_PD_MASK>>(32-SGX_FEATURE_ADDRESS_SPACE_SIZE));
-
+ /* External system cache violates this rule */
#if !defined (SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
-
-
-
+ /*
+ The heap must start on a PT boundary to avoid PT sharing across heaps
+ The only exception is the first heap which can start at any address
+ from 0 to the end of the first PT boundary
+ */
if(psDevArena->BaseDevVAddr.uiAddr > (pMMUHeap->ui32DataPageMask | pMMUHeap->ui32PTMask))
{
-
-
-
+ /*
+ if for some reason the first heap starts after the end of the first PT boundary
+ but is not aligned to a PT boundary then the assert will trigger unncessarily
+ */
PVR_ASSERT ((psDevArena->BaseDevVAddr.uiAddr
& (pMMUHeap->ui32DataPageMask
| pMMUHeap->ui32PTMask)) == 0);
}
#endif
-
+ /* how many PT entries do we need? */
pMMUHeap->ui32PTETotalUsable = pMMUHeap->psDevArena->ui32Size >> pMMUHeap->ui32PTShift;
-
+ /* calculate the PD Base index for the Heap (required for page mapping) */
pMMUHeap->ui32PDBaseIndex = (pMMUHeap->psDevArena->BaseDevVAddr.uiAddr & pMMUHeap->ui32PDMask) >> pMMUHeap->ui32PDShift;
-
-
-
+ /*
+ how many page tables?
+ round up to nearest entries to the nearest page table sized block
+ */
pMMUHeap->ui32PageTableCount = (pMMUHeap->ui32PTETotalUsable + pMMUHeap->ui32PTNumEntriesUsable - 1)
>> pMMUHeap->ui32PTBitWidth;
PVR_ASSERT(pMMUHeap->ui32PageTableCount > 0);
-
+ /* Create the arena */
pMMUHeap->psVMArena = RA_Create(psDevArena->pszName,
psDevArena->BaseDevVAddr.uiAddr,
psDevArena->ui32Size,
@@ -2360,7 +2999,7 @@ MMU_Create (MMU_CONTEXT *psMMUContext,
}
#if defined(PDUMP)
-
+ /* setup per-heap PDUMP MMU attributes */
MMU_SetPDumpAttribs(&pMMUHeap->sMMUAttrib,
psMMUContext->psDeviceNode,
pMMUHeap->ui32DataPageMask,
@@ -2372,51 +3011,35 @@ MMU_Create (MMU_CONTEXT *psMMUContext,
psDevArena->ui32Size,
pMMUHeap->ui32DataPageSize,
psDevArena->BaseDevVAddr.uiAddr);
-#endif
-
-#if 0
-
- if(psDevArena->ui32HeapID == SGX_TILED_HEAP_ID)
- {
- IMG_UINT32 ui32RegVal;
- IMG_UINT32 ui32XTileStride;
-
-
-
-
-
-
- ui32XTileStride = 2;
-
- ui32RegVal = (EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK
- & ((psDevArena->BaseDevVAddr.uiAddr>>20)
- << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT))
- |(EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK
- & (((psDevArena->BaseDevVAddr.uiAddr+psDevArena->ui32Size)>>20)
- << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT))
- |(EUR_CR_BIF_TILE0_CFG_MASK
- & (((ui32XTileStride<<1)|8) << EUR_CR_BIF_TILE0_CFG_SHIFT));
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_TILE0, ui32RegVal);
- }
-#endif
-
-
+#endif /* PDUMP */
+ /*
+ And return the RA for VM arena management
+ */
*ppsVMArena = pMMUHeap->psVMArena;
return pMMUHeap;
-
+ /* drop into here if errors */
ErrorFreePagetables:
_DeferredFreePageTables (pMMUHeap);
ErrorFreeHeap:
OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return IMG_NULL;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Delete
+
+ PURPOSE: Delete an MMU device virtual heap.
+
+ PARAMETERS: In: pMMUHeap - The MMU heap to delete.
+ RETURNS:
+******************************************************************************/
IMG_VOID
MMU_Delete (MMU_HEAP *pMMUHeap)
{
@@ -2434,7 +3057,7 @@ MMU_Delete (MMU_HEAP *pMMUHeap)
pMMUHeap->psDevArena->pszName,
pMMUHeap->psDevArena->BaseDevVAddr.uiAddr,
pMMUHeap->ui32PageTableCount);
-#endif
+#endif /* PDUMP */
#ifdef SUPPORT_SGX_MMU_BYPASS
EnableHostAccess(pMMUHeap->psMMUContext);
@@ -2445,10 +3068,23 @@ MMU_Delete (MMU_HEAP *pMMUHeap)
#endif
OSFreeMem (PVRSRV_OS_PAGEABLE_HEAP, sizeof(MMU_HEAP), pMMUHeap, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Alloc
+ PURPOSE: Allocate space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to allocate on.
+ In: uSize - Size in bytes to allocate.
+ Out: pActualSize - If non null receives actual size allocated.
+ In: uFlags - Allocation flags.
+ In: uDevVAddrAlignment - Required alignment.
+ Out: DevVAddr - Receives base address of allocation.
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failure
+******************************************************************************/
IMG_BOOL
MMU_Alloc (MMU_HEAP *pMMUHeap,
IMG_SIZE_T uSize,
@@ -2463,8 +3099,9 @@ MMU_Alloc (MMU_HEAP *pMMUHeap,
"MMU_Alloc: uSize=0x%x, flags=0x%x, align=0x%x",
uSize, uFlags, uDevVAddrAlignment));
-
-
+ /*
+ Only allocate a VM address if the caller did not supply one
+ */
if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
{
IMG_UINTPTR_T uiAddr;
@@ -2476,6 +3113,8 @@ MMU_Alloc (MMU_HEAP *pMMUHeap,
0,
uDevVAddrAlignment,
0,
+ IMG_NULL,
+ 0,
&uiAddr);
if(!bStatus)
{
@@ -2493,7 +3132,7 @@ MMU_Alloc (MMU_HEAP *pMMUHeap,
EnableHostAccess(pMMUHeap->psMMUContext);
#endif
-
+ /* allocate page tables to cover allocation as required */
bStatus = _DeferredAllocPagetables(pMMUHeap, *psDevVAddr, (IMG_UINT32)uSize);
#ifdef SUPPORT_SGX_MMU_BYPASS
@@ -2509,7 +3148,7 @@ MMU_Alloc (MMU_HEAP *pMMUHeap,
pMMUHeap->psDevArena->ui32HeapID));
if((uFlags & PVRSRV_MEM_USER_SUPPLIED_DEVVADDR) == 0)
{
-
+ /* free the VM address */
RA_Free (pMMUHeap->psVMArena, psDevVAddr->uiAddr, IMG_FALSE);
}
}
@@ -2517,6 +3156,14 @@ MMU_Alloc (MMU_HEAP *pMMUHeap,
return bStatus;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Free
+ PURPOSE: Free space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to deallocate on.
+ In: DevVAddr - Base address to deallocate.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
{
@@ -2546,21 +3193,52 @@ MMU_Free (MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR DevVAddr, IMG_UINT32 ui32Size)
pMMUHeap->psDevArena->ui32HeapID));
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Enable
+
+ PURPOSE: Enable an mmu. Establishes pages tables and takes the mmu out
+ of bypass and waits for the mmu to acknowledge enabled.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Enable (MMU_HEAP *pMMUHeap)
{
PVR_UNREFERENCED_PARAMETER(pMMUHeap);
-
+ /* SGX mmu is always enabled (stub function) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_Disable
+
+ PURPOSE: Disable an mmu, takes the mmu into bypass.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Disable (MMU_HEAP *pMMUHeap)
{
PVR_UNREFERENCED_PARAMETER(pMMUHeap);
-
+ /* SGX mmu is always enabled (stub function) */
}
#if defined(FIX_HW_BRN_31620)
+/*!
+******************************************************************************
+ FUNCTION: MMU_GetCacheFlushRange
+
+ PURPOSE: Gets device physical address of the mmu context.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: pui32RangeMask - Bit mask showing which PD cache
+ lines have changed
+ RETURNS: None
+******************************************************************************/
+
IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask)
{
IMG_UINT32 i;
@@ -2569,11 +3247,22 @@ IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32Range
{
pui32RangeMask[i] = pMMUContext->ui32PDChangeMask[i];
-
+ /* Clear bit mask for the next set of allocations */
pMMUContext->ui32PDChangeMask[i] = 0;
}
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_GetPDPhysAddr
+
+ PURPOSE: Gets device physical address of the mmu contexts PD.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: psDevPAddr - Address of PD
+ RETURNS: None
+******************************************************************************/
+
IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr)
{
*psDevPAddr = pMMUContext->sPDDevPAddr;
@@ -2581,6 +3270,19 @@ IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr
#endif
#if defined(PDUMP)
+/*!
+******************************************************************************
+ FUNCTION: MMU_PDumpPageTables
+
+ PURPOSE: PDump the linear mapping for a range of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: uSize - size of memory range in bytes
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
@@ -2596,22 +3298,25 @@ MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
IMG_UINT32 ui32PDIndex;
IMG_UINT32 ui32PTDumpCount;
-
+#if defined(FIX_HW_BRN_31620)
+ PVRSRV_SGXDEV_INFO *psDevInfo = pMMUHeap->psMMUContext->psDevInfo;
+#endif
+ /* find number of PT entries to dump */
ui32NumPTEntries = (IMG_UINT32)((uSize + pMMUHeap->ui32DataPageMask) >> pMMUHeap->ui32PTShift);
-
+ /* find the index/offset in PD entries */
ui32PDIndex = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* set the base PT info */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
-
+ /* find the index/offset of the first PT entry in the first PT page */
ui32PTIndex = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
-
+ /* pdump the PT Page modification */
PDUMPCOMMENT("Page table mods (num entries == %08X) %s", ui32NumPTEntries, bForUnmap ? "(for unmap)" : "");
-
+ /* walk the PT pages, dumping as we go */
while(ui32NumPTEntries > 0)
{
MMU_PT_INFO* psPTInfo = *ppsPTInfoList++;
@@ -2627,26 +3332,68 @@ MMU_PDumpPageTables (MMU_HEAP *pMMUHeap,
if (psPTInfo)
{
+#if defined(FIX_HW_BRN_31620)
+ IMG_UINT32 i;
+#endif
IMG_UINT32 ui32Flags = 0;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
ui32Flags |= ( MMU_IsHeapShared(pMMUHeap) ) ? PDUMP_FLAGS_PERSISTENT : 0;
#endif
pui32PTEntry = (IMG_UINT32*)psPTInfo->PTPageCpuVAddr;
- PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+#if defined(FIX_HW_BRN_31620)
+ if ((ui32PDIndex % (BRN31620_PDE_CACHE_FILL_SIZE/BRN31620_PT_ADDRESS_RANGE_SIZE)) == BRN31620_DUMMY_PDE_INDEX)
+ {
+ for (i=ui32PTIndex;i<(ui32PTIndex + ui32PTDumpCount);i++)
+ {
+ if (pui32PTEntry[i] == ((psDevInfo->sBRN31620DummyPageDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
+ | SGX_MMU_PTE_DUMMY_PAGE
+ | SGX_MMU_PTE_READONLY
+ | SGX_MMU_PTE_VALID))
+ {
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[i], sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
+ }
+ else
+ {
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[i], sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
+ }
+ }
+ else
+#endif
+ {
+ PDUMPMEMPTENTRIES(&pMMUHeap->sMMUAttrib, psPTInfo->hPTPageOSMemHandle, (IMG_VOID *) &pui32PTEntry[ui32PTIndex], ui32PTDumpCount * sizeof(IMG_UINT32), ui32Flags, IMG_FALSE, PDUMP_PT_UNIQUETAG, hUniqueTag);
+ }
}
-
+ /* decrement PT entries left */
ui32NumPTEntries -= ui32PTDumpCount;
-
+ /* reset offset in page */
ui32PTIndex = 0;
+
+#if defined(FIX_HW_BRN_31620)
+ /* For 31620 we need to know which PD index we're working on */
+ ui32PDIndex++;
+#endif
}
PDUMPCOMMENT("Finished page table mods %s", bForUnmap ? "(for unmap)" : "");
}
-#endif
+#endif /* #if defined(PDUMP) */
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapPage
+ PURPOSE: Create a mapping for one page at a specified virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: DevPAddr - the device physical address of the page to map.
+ In: ui32MemFlags - BM r/w/cache flags
+ RETURNS: None
+******************************************************************************/
static IMG_VOID
MMU_MapPage (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
@@ -2658,63 +3405,66 @@ MMU_MapPage (MMU_HEAP *pMMUHeap,
IMG_UINT32 ui32MMUFlags = 0;
MMU_PT_INFO **ppsPTInfoList;
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
-
-
+ /*
+ unravel the read/write/cache flags
+ */
if(((PVRSRV_MEM_READ|PVRSRV_MEM_WRITE) & ui32MemFlags) == (PVRSRV_MEM_READ|PVRSRV_MEM_WRITE))
{
-
+ /* read/write */
ui32MMUFlags = 0;
}
else if(PVRSRV_MEM_READ & ui32MemFlags)
{
-
+ /* read only */
ui32MMUFlags |= SGX_MMU_PTE_READONLY;
}
else if(PVRSRV_MEM_WRITE & ui32MemFlags)
{
-
+ /* write only */
ui32MMUFlags |= SGX_MMU_PTE_WRITEONLY;
}
-
+ /* cache coherency */
if(PVRSRV_MEM_CACHE_CONSISTENT & ui32MemFlags)
{
ui32MMUFlags |= SGX_MMU_PTE_CACHECONSISTENT;
}
#if !defined(FIX_HW_BRN_25503)
-
+ /* EDM protection */
if(PVRSRV_MEM_EDM_PROTECT & ui32MemFlags)
{
ui32MMUFlags |= SGX_MMU_PTE_EDMPROTECT;
}
#endif
-
-
+ /*
+ we receive a device physical address for the page that is to be mapped
+ and a device virtual address representing where it should be mapped to
+ */
-
+ /* find the index/offset in PD entries */
ui32Index = DevVAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
CheckPT(ppsPTInfoList[0]);
-
+ /* find the index/offset of the first PT in the first PT page */
ui32Index = (DevVAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
-
+ /* setup pointer to the first entry in the PT page */
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
#if !defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
{
IMG_UINT32 uTmp = pui32Tmp[ui32Index];
-
+ /* Is the current page already valid? (should not be unless it was allocated and not deallocated) */
#if defined(FIX_HW_BRN_31620)
if ((uTmp & SGX_MMU_PTE_VALID) && ((DevVAddr.uiAddr & BRN31620_PDE_CACHE_FILL_MASK) != BRN31620_DUMMY_PAGE_OFFSET))
#else
@@ -2728,6 +3478,9 @@ MMU_MapPage (MMU_HEAP *pMMUHeap,
ui32Index ));
PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Page table entry value: 0x%08X", uTmp));
PVR_DPF((PVR_DBG_ERROR, "MMU_MapPage: Physical page to map: 0x%08X", DevPAddr.uiAddr));
+#if PT_DUMP
+ DumpPT(ppsPTInfoList[0]);
+#endif
}
#if !defined(FIX_HW_BRN_31620)
PVR_ASSERT((uTmp & SGX_MMU_PTE_VALID) == 0);
@@ -2735,19 +3488,36 @@ MMU_MapPage (MMU_HEAP *pMMUHeap,
}
#endif
-
+ /* One more valid entry in the page table. */
ppsPTInfoList[0]->ui32ValidPTECount++;
-
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
+ /* map in the physical page */
pui32Tmp[ui32Index] = ((DevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
& ((~pMMUHeap->ui32DataPageMask)>>SGX_MMU_PTE_ADDR_ALIGNSHIFT))
| SGX_MMU_PTE_VALID
| ui32MMUFlags;
-
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
CheckPT(ppsPTInfoList[0]);
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapScatter
+
+ PURPOSE: Create a linear mapping for a range of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: psSysAddr - the device physical address of the page to
+ map.
+ In: uSize - size of memory range in bytes
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapScatter (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
@@ -2758,7 +3528,7 @@ MMU_MapScatter (MMU_HEAP *pMMUHeap,
{
#if defined(PDUMP)
IMG_DEV_VIRTADDR MapBaseDevVAddr;
-#endif
+#endif /*PDUMP*/
IMG_UINT32 uCount, i;
IMG_DEV_PHYADDR DevPAddr;
@@ -2768,7 +3538,7 @@ MMU_MapScatter (MMU_HEAP *pMMUHeap,
MapBaseDevVAddr = DevVAddr;
#else
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
-#endif
+#endif /*PDUMP*/
for (i=0, uCount=0; uCount<uSize; i++, uCount+=pMMUHeap->ui32DataPageSize)
{
@@ -2777,7 +3547,7 @@ MMU_MapScatter (MMU_HEAP *pMMUHeap,
sSysAddr = psSysAddr[i];
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((sSysAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sSysAddr);
@@ -2793,9 +3563,25 @@ MMU_MapScatter (MMU_HEAP *pMMUHeap,
#if defined(PDUMP)
MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapPages
+
+ PURPOSE: Create a linear mapping for a ranege of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to
+ map.
+ In: uSize - size of memory range in bytes
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapPages (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
@@ -2807,7 +3593,7 @@ MMU_MapPages (MMU_HEAP *pMMUHeap,
IMG_DEV_PHYADDR DevPAddr;
#if defined(PDUMP)
IMG_DEV_VIRTADDR MapBaseDevVAddr;
-#endif
+#endif /*PDUMP*/
IMG_UINT32 uCount;
IMG_UINT32 ui32VAdvance;
IMG_UINT32 ui32PAdvance;
@@ -2821,7 +3607,7 @@ MMU_MapPages (MMU_HEAP *pMMUHeap,
SysPAddr.uiAddr,
uSize));
-
+ /* set the virtual and physical advance */
ui32VAdvance = pMMUHeap->ui32DataPageSize;
ui32PAdvance = pMMUHeap->ui32DataPageSize;
@@ -2829,40 +3615,153 @@ MMU_MapPages (MMU_HEAP *pMMUHeap,
MapBaseDevVAddr = DevVAddr;
#else
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
-#endif
+#endif /*PDUMP*/
DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
-#if defined(FIX_HW_BRN_23281)
- if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
+ /*
+ for dummy allocations there is only one physical
+ page backing the virtual range
+ */
+ if(ui32MemFlags & PVRSRV_MEM_DUMMY)
{
- ui32VAdvance *= 2;
+ ui32PAdvance = 0;
}
+
+ for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+ {
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevVAddr.uiAddr += ui32VAdvance;
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
+
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
+}
+
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapPagesSparse
+
+ PURPOSE: Create a linear mapping for a ranege of pages at a specified
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to
+ map.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapPagesSparse (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_DEV_PHYADDR DevPAddr;
+#if defined(PDUMP)
+ IMG_DEV_VIRTADDR MapBaseDevVAddr;
+#endif /*PDUMP*/
+ IMG_UINT32 uCount;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+ IMG_SIZE_T uSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+#if !defined(PVRSRV_NEED_PVR_DPF)
+ PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
#endif
-
+ PVR_ASSERT (pMMUHeap != IMG_NULL);
+ PVR_DPF ((PVR_DBG_MESSAGE, "MMU_MapPagesSparse: heap:%s, heap_id:%d devVAddr=%08X, SysPAddr=%08X, VM space=0x%x, PHYS space=0x%x",
+ pMMUHeap->psDevArena->pszName,
+ pMMUHeap->psDevArena->ui32HeapID,
+ DevVAddr.uiAddr,
+ SysPAddr.uiAddr,
+ uSizeVM,
+ ui32ChunkSize * ui32NumPhysChunks));
+
+ /* set the virtual and physical advance */
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+#if defined(PDUMP)
+ MapBaseDevVAddr = DevVAddr;
+#else
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif /*PDUMP*/
+ DevPAddr = SysSysPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, SysPAddr);
+
+ /* check the physical alignment of the memory to map */
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ /*
+ for dummy allocations there is only one physical
+ page backing the virtual range
+ */
if(ui32MemFlags & PVRSRV_MEM_DUMMY)
{
ui32PAdvance = 0;
}
- for (uCount=0; uCount<uSize; uCount+=ui32VAdvance)
+ for (uCount=0; uCount<uSizeVM; uCount+=ui32VAdvance)
{
- MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ if (pabMapChunk[uCount/ui32ChunkSize])
+ {
+ MMU_MapPage (pMMUHeap, DevVAddr, DevPAddr, ui32MemFlags);
+ DevPAddr.uiAddr += ui32PAdvance;
+ }
DevVAddr.uiAddr += ui32VAdvance;
- DevPAddr.uiAddr += ui32PAdvance;
}
+ pMMUHeap->bHasSparseMappings = IMG_TRUE;
#if defined(PDUMP)
- MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSize, IMG_FALSE, hUniqueTag);
-#endif
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uSizeVM, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapShadow
+
+ PURPOSE: Create a mapping for a range of pages from either a CPU
+ virtual adddress, (or if NULL a hOSMemHandle) to a specified
+ device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: uByteSize - A page aligned mapping length in bytes.
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated - It used to return a byte aligned
+ device virtual address corresponding to the
+ cpu virtual address (When CpuVAddr wasn't
+ constrained to be page aligned.) Now it just
+ returns MapBaseDevVAddr. Unaligned semantics
+ can easily be handled above this API if required.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapShadow (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR MapBaseDevVAddr,
@@ -2889,31 +3788,25 @@ MMU_MapShadow (MMU_HEAP *pMMUHeap,
uByteSize,
(IMG_UINTPTR_T)CpuVAddr));
-
+ /* set the virtual and physical advance */
ui32VAdvance = pMMUHeap->ui32DataPageSize;
ui32PAdvance = pMMUHeap->ui32DataPageSize;
-
+ /* note: can't do useful check on the CPU Addr other than it being at least 4k alignment */
PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
PVR_ASSERT(((IMG_UINT32)uByteSize & pMMUHeap->ui32DataPageMask) == 0);
pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
-#if defined(FIX_HW_BRN_23281)
- if(ui32MemFlags & PVRSRV_MEM_INTERLEAVED)
- {
- ui32VAdvance *= 2;
- }
-#endif
-
-
-
-
+ /*
+ for dummy allocations there is only one physical
+ page backing the virtual range
+ */
if(ui32MemFlags & PVRSRV_MEM_DUMMY)
{
ui32PAdvance = 0;
}
-
+ /* Loop through cpu memory and map page by page */
MapDevVAddr = MapBaseDevVAddr;
for (i=0; i<uByteSize; i+=ui32VAdvance)
{
@@ -2931,7 +3824,7 @@ MMU_MapShadow (MMU_HEAP *pMMUHeap,
}
DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
-
+ /* check the physical alignment of the memory to map */
PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
PVR_DPF ((PVR_DBG_MESSAGE,
@@ -2944,17 +3837,157 @@ MMU_MapShadow (MMU_HEAP *pMMUHeap,
MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
-
+ /* loop update */
MapDevVAddr.uiAddr += ui32VAdvance;
uOffset += ui32PAdvance;
}
#if defined(PDUMP)
MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uByteSize, IMG_FALSE, hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
+}
+
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapShadowSparse
+
+ PURPOSE: Create a mapping for a range of pages from either a CPU
+ virtual adddress, (or if NULL a hOSMemHandle) to a specified
+ device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated - It used to return a byte aligned
+ device virtual address corresponding to the
+ cpu virtual address (When CpuVAddr wasn't
+ constrained to be page aligned.) Now it just
+ returns MapBaseDevVAddr. Unaligned semantics
+ can easily be handled above this API if required.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadowSparse (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 uOffset = 0;
+ IMG_DEV_VIRTADDR MapDevVAddr;
+ IMG_UINT32 ui32VAdvance;
+ IMG_UINT32 ui32PAdvance;
+ IMG_SIZE_T uiSizeVM = ui32ChunkSize * ui32NumVirtChunks;
+ IMG_UINT32 ui32ChunkIndex = 0;
+ IMG_UINT32 ui32ChunkOffset = 0;
+#if !defined(PVRSRV_NEED_PVR_DPF)
+ PVR_UNREFERENCED_PARAMETER(ui32NumPhysChunks);
+#endif
+#if !defined (PDUMP)
+ PVR_UNREFERENCED_PARAMETER(hUniqueTag);
+#endif
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "MMU_MapShadowSparse: DevVAddr:%08X, VM space:0x%x, CPUVAddr:%08X PHYS space:0x%x",
+ MapBaseDevVAddr.uiAddr,
+ uiSizeVM,
+ (IMG_UINTPTR_T)CpuVAddr,
+ ui32ChunkSize * ui32NumPhysChunks));
+
+ /* set the virtual and physical advance */
+ ui32VAdvance = pMMUHeap->ui32DataPageSize;
+ ui32PAdvance = pMMUHeap->ui32DataPageSize;
+
+ /* note: can't do useful check on the CPU Addr other than it being at least 4k alignment */
+ PVR_ASSERT(((IMG_UINTPTR_T)CpuVAddr & (SGX_MMU_PAGE_SIZE - 1)) == 0);
+ PVR_ASSERT(((IMG_UINT32)uiSizeVM & pMMUHeap->ui32DataPageMask) == 0);
+ pDevVAddr->uiAddr = MapBaseDevVAddr.uiAddr;
+
+ /* Shouldn't come through the sparse interface */
+ PVR_ASSERT((ui32MemFlags & PVRSRV_MEM_DUMMY) == 0);
+
+ /* Loop through cpu memory and map page by page */
+ MapDevVAddr = MapBaseDevVAddr;
+ for (i=0; i<uiSizeVM; i+=ui32VAdvance)
+ {
+ IMG_CPU_PHYADDR CpuPAddr;
+ IMG_DEV_PHYADDR DevPAddr;
+
+ if (pabMapChunk[i/ui32ChunkSize])
+ /*if (pabMapChunk[ui32ChunkIndex])*/
+ {
+ if(CpuVAddr)
+ {
+ CpuPAddr = OSMapLinToCPUPhys (hOSMemHandle,
+ (IMG_VOID *)((IMG_UINTPTR_T)CpuVAddr + uOffset));
+ }
+ else
+ {
+ CpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, uOffset);
+ }
+ DevPAddr = SysCpuPAddrToDevPAddr (PVRSRV_DEVICE_TYPE_SGX, CpuPAddr);
+
+ /* check the physical alignment of the memory to map */
+ PVR_ASSERT((DevPAddr.uiAddr & pMMUHeap->ui32DataPageMask) == 0);
+
+ PVR_DPF ((PVR_DBG_MESSAGE,
+ "Offset=0x%x: CpuVAddr=%08X, CpuPAddr=%08X, DevVAddr=%08X, DevPAddr=%08X",
+ uOffset,
+ (IMG_UINTPTR_T)CpuVAddr + uOffset,
+ CpuPAddr.uiAddr,
+ MapDevVAddr.uiAddr,
+ DevPAddr.uiAddr));
+
+ MMU_MapPage (pMMUHeap, MapDevVAddr, DevPAddr, ui32MemFlags);
+ uOffset += ui32PAdvance;
+ }
+
+ /* loop update */
+ MapDevVAddr.uiAddr += ui32VAdvance;
+
+ if (ui32ChunkOffset == ui32ChunkSize)
+ {
+ ui32ChunkIndex++;
+ ui32ChunkOffset = 0;
+ }
+ }
+
+ pMMUHeap->bHasSparseMappings = IMG_TRUE;
+#if defined(PDUMP)
+ MMU_PDumpPageTables (pMMUHeap, MapBaseDevVAddr, uiSizeVM, IMG_FALSE, hUniqueTag);
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_UnmapPages
+
+ PURPOSE: unmap pages and invalidate virtual address
+ PARAMETERS: In: psMMUHeap - the mmu.
+ In: sDevVAddr - the device virtual address.
+ In: ui32PageCount - page count
+ In: hUniqueTag - A unique ID for use as a tag identifier
+
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_UnmapPages (MMU_HEAP *psMMUHeap,
IMG_DEV_VIRTADDR sDevVAddr,
@@ -2972,24 +4005,24 @@ MMU_UnmapPages (MMU_HEAP *psMMUHeap,
PVR_UNREFERENCED_PARAMETER(hUniqueTag);
#endif
-
+ /* setup tmp devvaddr to base of allocation */
sTmpDevVAddr = sDevVAddr;
for(i=0; i<ui32PageCount; i++)
{
MMU_PT_INFO **ppsPTInfoList;
-
+ /* find the index/offset in PD entries */
ui32PDIndex = sTmpDevVAddr.uiAddr >> psMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &psMMUHeap->psMMUContext->apsPTInfoList[ui32PDIndex];
-
+ /* find the index/offset of the first PT in the first PT page */
ui32PTIndex = (sTmpDevVAddr.uiAddr & psMMUHeap->ui32PTMask) >> psMMUHeap->ui32PTShift;
-
- if (!ppsPTInfoList[0])
+ /* Is the PT page valid? */
+ if ((!ppsPTInfoList[0]) && (!psMMUHeap->bHasSparseMappings))
{
PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: ERROR Invalid PT for alloc at VAddr:0x%08X (VaddrIni:0x%08X AllocPage:%u) PDIdx:%u PTIdx:%u",
sTmpDevVAddr.uiAddr,
@@ -2998,19 +4031,19 @@ MMU_UnmapPages (MMU_HEAP *psMMUHeap,
ui32PDIndex,
ui32PTIndex));
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += uPageSize;
-
+ /* Try to unmap the remaining allocation pages */
continue;
}
CheckPT(ppsPTInfoList[0]);
-
+ /* setup pointer to the first entry in the PT page */
pui32Tmp = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
-
+ /* Decrement the valid page count only if the current page is valid*/
if (pui32Tmp[ui32PTIndex] & SGX_MMU_PTE_VALID)
{
ppsPTInfoList[0]->ui32ValidPTECount--;
@@ -3026,25 +4059,27 @@ MMU_UnmapPages (MMU_HEAP *psMMUHeap,
PVR_DPF((PVR_DBG_ERROR, "MMU_UnmapPages: Page table entry value: 0x%08X", pui32Tmp[ui32PTIndex]));
}
-
+ /* The page table count should not go below zero */
PVR_ASSERT((IMG_INT32)ppsPTInfoList[0]->ui32ValidPTECount >= 0);
+ MakeKernelPageReadWrite(ppsPTInfoList[0]->PTPageCpuVAddr);
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* point the PT entry to the dummy data page */
pui32Tmp[ui32PTIndex] = (psMMUHeap->psMMUContext->psDevInfo->sDummyDataDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
#else
-
+ /* invalidate entry */
#if defined(FIX_HW_BRN_31620)
BRN31620InvalidatePageTableEntry(psMMUHeap->psMMUContext, ui32PDIndex, ui32PTIndex, &pui32Tmp[ui32PTIndex]);
#else
pui32Tmp[ui32PTIndex] = 0;
#endif
#endif
+ MakeKernelPageReadOnly(ppsPTInfoList[0]->PTPageCpuVAddr);
CheckPT(ppsPTInfoList[0]);
-
+ /* advance the sTmpDevVAddr by one page */
sTmpDevVAddr.uiAddr += uPageSize;
}
@@ -3052,10 +4087,21 @@ MMU_UnmapPages (MMU_HEAP *psMMUHeap,
#if defined(PDUMP)
MMU_PDumpPageTables (psMMUHeap, sDevVAddr, uPageSize*ui32PageCount, IMG_TRUE, hUniqueTag);
-#endif
+#endif /* #if defined(PDUMP) */
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_GetPhysPageAddr
+
+ PURPOSE: extracts physical address from MMU page tables
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ PARAMETERS: In: sDevVPageAddr - the virtual address to extract physical
+ page mapping from
+ RETURNS: None
+******************************************************************************/
IMG_DEV_PHYADDR
MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
{
@@ -3064,31 +4110,35 @@ MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr)
IMG_DEV_PHYADDR sDevPAddr;
MMU_PT_INFO **ppsPTInfoList;
-
+ /* find the index/offset in PD entries */
ui32Index = sDevVPageAddr.uiAddr >> pMMUHeap->ui32PDShift;
-
+ /* and advance to the first PT info list */
ppsPTInfoList = &pMMUHeap->psMMUContext->apsPTInfoList[ui32Index];
if (!ppsPTInfoList[0])
{
- PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ /* Heaps with sparse mappings are allowed invalid pages */
+ if (!pMMUHeap->bHasSparseMappings)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"MMU_GetPhysPageAddr: Not mapped in at 0x%08x", sDevVPageAddr.uiAddr));
+ }
sDevPAddr.uiAddr = 0;
return sDevPAddr;
}
-
+ /* find the index/offset of the first PT in the first PT page */
ui32Index = (sDevVPageAddr.uiAddr & pMMUHeap->ui32PTMask) >> pMMUHeap->ui32PTShift;
-
+ /* setup pointer to the first entry in the PT page */
pui32PageTable = (IMG_UINT32*)ppsPTInfoList[0]->PTPageCpuVAddr;
-
+ /* read back physical page */
sDevPAddr.uiAddr = pui32PageTable[ui32Index];
-
+ /* Mask off non-address bits */
sDevPAddr.uiAddr &= ~(pMMUHeap->ui32DataPageMask>>SGX_MMU_PTE_ADDR_ALIGNSHIFT);
-
+ /* and align the address */
sDevPAddr.uiAddr <<= SGX_MMU_PTE_ADDR_ALIGNSHIFT;
return sDevPAddr;
@@ -3101,6 +4151,18 @@ IMG_DEV_PHYADDR MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext)
}
+/*!
+******************************************************************************
+ FUNCTION: SGXGetPhysPageAddr
+
+ PURPOSE: Gets DEV and CPU physical address of sDevVAddr
+
+ PARAMETERS: In: hDevMemHeap - device mem heap handle
+ PARAMETERS: In: sDevVAddr - the base virtual address to unmap from
+ PARAMETERS: Out: pDevPAddr - DEV physical address
+ PARAMETERS: Out: pCpuPAddr - CPU physical address
+ RETURNS: None
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
IMG_DEV_VIRTADDR sDevVAddr,
@@ -3110,18 +4172,30 @@ PVRSRV_ERROR SGXGetPhysPageAddrKM (IMG_HANDLE hDevMemHeap,
MMU_HEAP *pMMUHeap;
IMG_DEV_PHYADDR DevPAddr;
-
-
+ /*
+ Get MMU Heap From hDevMemHeap
+ */
pMMUHeap = (MMU_HEAP*)BM_GetMMUHeap(hDevMemHeap);
DevPAddr = MMU_GetPhysPageAddr(pMMUHeap, sDevVAddr);
- pCpuPAddr->uiAddr = DevPAddr.uiAddr;
+ pCpuPAddr->uiAddr = DevPAddr.uiAddr; /* SysDevPAddrToCPUPAddr(DevPAddr) */
pDevPAddr->uiAddr = DevPAddr.uiAddr;
return (pDevPAddr->uiAddr != 0) ? PVRSRV_OK : PVRSRV_ERROR_INVALID_PARAMS;
}
+/*!
+******************************************************************************
+ FUNCTION: SGXGetMMUPDAddrKM
+
+ PURPOSE: Gets PD device physical address of hDevMemContext
+
+ PARAMETERS: In: hDevCookie - device cookie
+ PARAMETERS: In: hDevMemContext - memory context
+ PARAMETERS: Out: psPDDevPAddr - MMU PD address
+ RETURNS: None
+******************************************************************************/
PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
IMG_HANDLE hDevMemContext,
IMG_DEV_PHYADDR *psPDDevPAddr)
@@ -3131,12 +4205,24 @@ PVRSRV_ERROR SGXGetMMUPDAddrKM(IMG_HANDLE hDevCookie,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* return the address */
*psPDDevPAddr = ((BM_CONTEXT*)hDevMemContext)->psMMUContext->sPDDevPAddr;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDAlloc
+
+ PURPOSE: Allocate a dummy Page Directory, Page Table and Page which can
+ be used for dynamic dummy page mapping during SGX reset.
+ Note: since this is only used for hardware recovery, no
+ pdumping is performed.
+
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS: PVRSRV_OK or error
+******************************************************************************/
PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
{
PVRSRV_ERROR eError;
@@ -3151,13 +4237,16 @@ PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
+ /* allocate 3 pages - for the PD, PT and dummy page */
if(psLocalDevMemArena == IMG_NULL)
{
-
+ /* UMA system */
eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
3 * SGX_MMU_PAGE_SIZE,
SGX_MMU_PAGE_SIZE,
+ IMG_NULL,
+ 0,
+ IMG_NULL,
(IMG_VOID **)&pui8MemBlock,
&hOSMemHandle);
if (eError != PVRSRV_OK)
@@ -3166,7 +4255,7 @@ PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
return eError;
}
-
+ /* translate address to device physical */
if(pui8MemBlock)
{
sMemBlockCpuPAddr = OSMapLinToCPUPhys(hOSMemHandle,
@@ -3174,13 +4263,14 @@ PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
}
else
{
-
+ /* This isn't used in all cases since not all ports currently support
+ * OSMemHandleToCpuPAddr() */
sMemBlockCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, 0);
}
}
else
{
-
+ /* non-UMA system */
if(RA_Alloc(psLocalDevMemArena,
3 * SGX_MMU_PAGE_SIZE,
@@ -3189,13 +4279,15 @@ PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
0,
SGX_MMU_PAGE_SIZE,
0,
+ IMG_NULL,
+ 0,
&(sMemBlockSysPAddr.uiAddr)) != IMG_TRUE)
{
PVR_DPF((PVR_DBG_ERROR, "MMU_BIFResetPDAlloc: ERROR call to RA_Alloc failed"));
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* derive the CPU virtual address */
sMemBlockCpuPAddr = SysSysPAddrToCpuPAddr(sMemBlockSysPAddr);
pui8MemBlock = OSMapPhysToLin(sMemBlockCpuPAddr,
SGX_MMU_PAGE_SIZE * 3,
@@ -3212,20 +4304,29 @@ PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo)
psDevInfo->sBIFResetPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sMemBlockCpuPAddr);
psDevInfo->sBIFResetPTDevPAddr.uiAddr = psDevInfo->sBIFResetPDDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
psDevInfo->sBIFResetPageDevPAddr.uiAddr = psDevInfo->sBIFResetPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
-
-
+ /* override pointer cast warnings */
+ /* PRQA S 3305,509 2 */
psDevInfo->pui32BIFResetPD = (IMG_UINT32 *)pui8MemBlock;
psDevInfo->pui32BIFResetPT = (IMG_UINT32 *)(pui8MemBlock + SGX_MMU_PAGE_SIZE);
-
+ /* Invalidate entire PD and PT. */
OSMemSet(psDevInfo->pui32BIFResetPD, 0, SGX_MMU_PAGE_SIZE);
OSMemSet(psDevInfo->pui32BIFResetPT, 0, SGX_MMU_PAGE_SIZE);
-
+ /* Fill dummy page with markers. */
OSMemSet(pui8MemBlock + (2 * SGX_MMU_PAGE_SIZE), 0xDB, SGX_MMU_PAGE_SIZE);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDFree
+
+ PURPOSE: Free resources allocated in MMU_BIFResetPDAlloc.
+
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS:
+******************************************************************************/
IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
{
SYS_DATA *psSysData;
@@ -3236,7 +4337,7 @@ IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
+ /* free the page directory */
if(psLocalDevMemArena == IMG_NULL)
{
OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
@@ -3256,274 +4357,60 @@ IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo)
}
}
-
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode)
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32FaultAddr)
{
- PVRSRV_ERROR eError;
- SYS_DATA *psSysData;
- RA_ARENA *psLocalDevMemArena;
- IMG_HANDLE hPTPageOSMemHandle = IMG_NULL;
- IMG_HANDLE hPDPageOSMemHandle = IMG_NULL;
- IMG_UINT32 *pui32PD = IMG_NULL;
- IMG_UINT32 *pui32PT = IMG_NULL;
- IMG_CPU_PHYADDR sCpuPAddr;
- IMG_DEV_PHYADDR sPTDevPAddr;
- IMG_DEV_PHYADDR sPDDevPAddr;
- PVRSRV_SGXDEV_INFO *psDevInfo;
- IMG_UINT32 ui32PDOffset;
- IMG_UINT32 ui32PTOffset;
+ MMU_CONTEXT *psMMUContext = psDevInfo->pvMMUContextList;
- psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
-
- SysAcquireData(&psSysData);
-
- psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
-
- if(psLocalDevMemArena == IMG_NULL)
+ while (psMMUContext && (psMMUContext->sPDDevPAddr.uiAddr != ui32PDDevPAddr))
{
-
- eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- (IMG_VOID **)&pui32PT,
- &hPTPageOSMemHandle);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
- return eError;
- }
- ui32PTOffset = 0;
-
- eError = OSAllocPages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- SGX_MMU_PAGE_SIZE,
- (IMG_VOID **)&pui32PD,
- &hPDPageOSMemHandle);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to OSAllocPages failed"));
- return eError;
- }
- ui32PDOffset = 0;
-
-
- if(pui32PT)
- {
- sCpuPAddr = OSMapLinToCPUPhys(hPTPageOSMemHandle,
- pui32PT);
- }
- else
- {
-
- sCpuPAddr = OSMemHandleToCpuPAddr(hPTPageOSMemHandle, 0);
- }
- sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
- if(pui32PD)
- {
- sCpuPAddr = OSMapLinToCPUPhys(hPDPageOSMemHandle,
- pui32PD);
- }
- else
- {
-
- sCpuPAddr = OSMemHandleToCpuPAddr(hPDPageOSMemHandle, 0);
- }
- sPDDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
- }
- else
- {
-
-
- if(RA_Alloc(psLocalDevMemArena,
- SGX_MMU_PAGE_SIZE * 2,
- IMG_NULL,
- IMG_NULL,
- 0,
- SGX_MMU_PAGE_SIZE,
- 0,
- &(psDevInfo->sBRN22997SysPAddr.uiAddr))!= IMG_TRUE)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR call to RA_Alloc failed"));
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
-
-
- sCpuPAddr = SysSysPAddrToCpuPAddr(psDevInfo->sBRN22997SysPAddr);
- pui32PT = OSMapPhysToLin(sCpuPAddr,
- SGX_MMU_PAGE_SIZE * 2,
- PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
- &hPTPageOSMemHandle);
- if(!pui32PT)
- {
- PVR_DPF((PVR_DBG_ERROR, "WorkaroundBRN22997: ERROR failed to map page tables"));
- return PVRSRV_ERROR_BAD_MAPPING;
- }
- ui32PTOffset = 0;
-
-
- sPTDevPAddr = SysCpuPAddrToDevPAddr(PVRSRV_DEVICE_TYPE_SGX, sCpuPAddr);
-
- pui32PD = pui32PT + SGX_MMU_PAGE_SIZE/sizeof(IMG_UINT32);
- ui32PDOffset = SGX_MMU_PAGE_SIZE;
- hPDPageOSMemHandle = hPTPageOSMemHandle;
- sPDDevPAddr.uiAddr = sPTDevPAddr.uiAddr + SGX_MMU_PAGE_SIZE;
+ psMMUContext = psMMUContext->psNext;
}
- OSMemSet(pui32PD, 0, SGX_MMU_PAGE_SIZE);
- OSMemSet(pui32PT, 0, SGX_MMU_PAGE_SIZE);
-
-
- PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPDPageOSMemHandle, ui32PDOffset, pui32PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
- PDUMPMALLOCPAGETABLE(&psDeviceNode->sDevId, hPTPageOSMemHandle, ui32PTOffset, pui32PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, hPTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
-
- psDevInfo->hBRN22997PTPageOSMemHandle = hPTPageOSMemHandle;
- psDevInfo->hBRN22997PDPageOSMemHandle = hPDPageOSMemHandle;
- psDevInfo->sBRN22997PTDevPAddr = sPTDevPAddr;
- psDevInfo->sBRN22997PDDevPAddr = sPDDevPAddr;
- psDevInfo->pui32BRN22997PD = pui32PD;
- psDevInfo->pui32BRN22997PT = pui32PT;
-
- return PVRSRV_OK;
-}
-
-
-IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo)
-{
- IMG_UINT32 *pui32PD = psDevInfo->pui32BRN22997PD;
- IMG_UINT32 *pui32PT = psDevInfo->pui32BRN22997PT;
- IMG_UINT32 ui32PDIndex;
- IMG_UINT32 ui32PTIndex;
- IMG_DEV_VIRTADDR sDevVAddr;
- volatile IMG_UINT32 *pui32HostPort;
- IMG_UINT32 ui32BIFCtrl;
-
-
-
-
- pui32HostPort = (volatile IMG_UINT32*)(((IMG_UINT8*)psDevInfo->pvHostPortBaseKM) + SYS_SGX_HOSTPORT_BRN23030_OFFSET);
-
-
- sDevVAddr.uiAddr = SYS_SGX_HOSTPORT_BASE_DEVVADDR + SYS_SGX_HOSTPORT_BRN23030_OFFSET;
-
- ui32PDIndex = (sDevVAddr.uiAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
- ui32PTIndex = (sDevVAddr.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
-
-
- pui32PD[ui32PDIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
- | SGX_MMU_PDE_VALID;
-
- pui32PT[ui32PTIndex] = (psDevInfo->sBRN22997PTDevPAddr.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
- | SGX_MMU_PTE_VALID;
-
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
-
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0,
- psDevInfo->sBRN22997PDDevPAddr.uiAddr);
- PDUMPPDREG(&psDevInfo->sMMUAttrib, EUR_CR_BIF_DIR_LIST_BASE0, psDevInfo->sBRN22997PDDevPAddr.uiAddr, PDUMP_PD_UNIQUETAG);
-
-
- ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
-
-
- if (pui32HostPort)
- {
-
- IMG_UINT32 ui32Tmp;
- ui32Tmp = *pui32HostPort;
- }
- else
+ if (psMMUContext)
{
- PVR_DPF((PVR_DBG_ERROR,"Host Port not present for BRN22997 workaround"));
- }
-
-
-
-
-
-
-
- PDUMPCOMMENT("RDW :SGXMEM:v4:%08X\r\n", sDevVAddr.uiAddr);
-
- PDUMPCOMMENT("SAB :SGXMEM:v4:%08X 4 0 hostport.bin", sDevVAddr.uiAddr);
-
-
- pui32PD[ui32PDIndex] = 0;
- pui32PT[ui32PTIndex] = 0;
+ IMG_UINT32 ui32PTIndex;
+ IMG_UINT32 ui32PDIndex;
-
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PDPageOSMemHandle, pui32PD, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
- PDUMPMEMPTENTRIES(&psDevInfo->sMMUAttrib, psDevInfo->hBRN22997PTPageOSMemHandle, pui32PT, SGX_MMU_PAGE_SIZE, 0, IMG_TRUE, PDUMP_PT_UNIQUETAG, PDUMP_PD_UNIQUETAG);
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_INVALDC_MASK);
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
- PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32BIFCtrl);
-}
-
-
-IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode)
-{
- SYS_DATA *psSysData;
- RA_ARENA *psLocalDevMemArena;
- PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO*)psDeviceNode->pvDevice;
-
-
- SysAcquireData(&psSysData);
-
- psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
+ PVR_LOG(("Found MMU context for page fault 0x%08x", ui32FaultAddr));
+ PVR_LOG(("GPU memory context is for PID=%d (%s)", psMMUContext->ui32PID, psMMUContext->szName));
- PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PDPageOSMemHandle, psDevInfo->pui32BRN22997PD, SGX_MMU_PAGE_SIZE, 0, PDUMP_PD_UNIQUETAG);
- PDUMPFREEPAGETABLE(&psDeviceNode->sDevId, psDevInfo->hBRN22997PTPageOSMemHandle, psDevInfo->pui32BRN22997PT, SGX_MMU_PAGE_SIZE, 0, PDUMP_PT_UNIQUETAG);
+ ui32PTIndex = (ui32FaultAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
+ ui32PDIndex = (ui32FaultAddr & SGX_MMU_PD_MASK) >> (SGX_MMU_PT_SHIFT + SGX_MMU_PAGE_SHIFT);
-
- if(psLocalDevMemArena == IMG_NULL)
- {
- if (psDevInfo->pui32BRN22997PD != IMG_NULL)
+ if (psMMUContext->apsPTInfoList[ui32PDIndex])
{
- OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- psDevInfo->pui32BRN22997PD,
- psDevInfo->hBRN22997PDPageOSMemHandle);
- }
+ if (psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
+ {
+ IMG_UINT32 *pui32Ptr = psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
+ IMG_UINT32 ui32PTE = pui32Ptr[ui32PTIndex];
- if (psDevInfo->pui32BRN22997PT != IMG_NULL)
- {
- OSFreePages(PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_KERNEL_ONLY,
- SGX_MMU_PAGE_SIZE,
- psDevInfo->pui32BRN22997PT,
- psDevInfo->hBRN22997PTPageOSMemHandle);
+ PVR_LOG(("PDE valid: PTE = 0x%08x (PhysAddr = 0x%08x, %s)",
+ ui32PTE,
+ ui32PTE & SGX_MMU_PTE_ADDR_MASK,
+ ui32PTE & SGX_MMU_PTE_VALID?"valid":"Invalid"));
+ }
+ else
+ {
+ PVR_LOG(("Found PT info but no CPU address"));
+ }
}
- }
- else
- {
- if (psDevInfo->pui32BRN22997PT != IMG_NULL)
+ else
{
- OSUnMapPhysToLin(psDevInfo->pui32BRN22997PT,
- SGX_MMU_PAGE_SIZE * 2,
- PVRSRV_HAP_WRITECOMBINE|PVRSRV_HAP_KERNEL_ONLY,
- psDevInfo->hBRN22997PTPageOSMemHandle);
-
-
- RA_Free(psLocalDevMemArena, psDevInfo->sBRN22997SysPAddr.uiAddr, IMG_FALSE);
+ PVR_LOG(("No PDE found"));
}
}
}
-#endif
-
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*!
+******************************************************************************
+ FUNCTION: MMU_MapExtSystemCacheRegs
+
+ PURPOSE: maps external system cache control registers into SGX MMU
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
{
IMG_UINT32 *pui32PT;
@@ -3555,12 +4442,13 @@ PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
pui32PT = (IMG_UINT32 *) psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr;
-
+ MakeKernelPageReadWrite(pui32PT);
+ /* map the PT to the registers */
pui32PT[ui32PTIndex] = (psDevInfo->sExtSysCacheRegsDevPBase.uiAddr>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
-
+ MakeKernelPageReadOnly(pui32PT);
#if defined(PDUMP)
-
+ /* Add the entery to the PT */
{
IMG_DEV_PHYADDR sDevPAddr;
IMG_CPU_PHYADDR sCpuPAddr;
@@ -3598,6 +4486,15 @@ PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
}
+/*!
+******************************************************************************
+ FUNCTION: MMU_UnmapExtSystemCacheRegs
+
+ PURPOSE: unmaps external system cache control registers
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
{
SYS_DATA *psSysData;
@@ -3621,11 +4518,11 @@ PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
psLocalDevMemArena = psSysData->apsLocalDevMemArena[0];
-
+ /* unmap the MMU page table from the PD */
ui32PDIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PD_MASK) >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
ui32PTIndex = (SGX_EXT_SYSTEM_CACHE_REGS_DEVVADDR_BASE & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
-
+ /* Only unmap it if the PT hasn't already been freed */
if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex])
{
if (psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->apsPTInfoList[ui32PDIndex]->PTPageCpuVAddr)
@@ -3634,7 +4531,9 @@ PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
}
}
+ MakeKernelPageReadWrite(pui32PT);
pui32PT[ui32PTIndex] = 0;
+ MakeKernelPageReadOnly(pui32PT);
PDUMPMEMPTENTRIES(&sMMUAttrib, psDeviceNode->sDevMemoryInfo.pBMKernelContext->psMMUContext->hPDOSMemHandle, &pui32PT[ui32PTIndex], sizeof(IMG_UINT32), 0, IMG_FALSE, PDUMP_PD_UNIQUETAG, PDUMP_PT_UNIQUETAG);
@@ -3644,6 +4543,16 @@ PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode)
#if PAGE_TEST
+/*!
+******************************************************************************
+ FUNCTION: PageTest
+
+ PURPOSE: Tests page table memory, for use during device bring-up.
+
+ PARAMETERS: In: void* pMem - page address (CPU mapped)
+ PARAMETERS: In: IMG_DEV_PHYADDR sDevPAddr - page device phys address
+ RETURNS: None, provides debug output and breaks if an error is detected.
+******************************************************************************/
static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
{
volatile IMG_UINT32 ui32WriteData;
@@ -3661,7 +4570,7 @@ static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
if (ui32WriteData != ui32ReadData)
{
-
+ // Mem fault
PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
PVR_DBG_BREAK;
bOK = IMG_FALSE;
@@ -3677,7 +4586,7 @@ static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
if (ui32WriteData != ui32ReadData)
{
-
+ // Mem fault
PVR_DPF ((PVR_DBG_ERROR, "Error - memory page test failed at device phys address 0x%08X", sDevPAddr.uiAddr + (n<<2) ));
PVR_DBG_BREAK;
bOK = IMG_FALSE;
@@ -3695,3 +4604,8 @@ static IMG_VOID PageTest(IMG_VOID* pMem, IMG_DEV_PHYADDR sDevPAddr)
}
#endif
+/******************************************************************************
+ End of file (mmu.c)
+******************************************************************************/
+
+
diff --git a/sgx/services4/srvkm/devices/sgx/mmu.h b/sgx/services4/srvkm/devices/sgx/mmu.h
index 59b24c4..4d5160e 100644
--- a/sgx/services4/srvkm/devices/sgx/mmu.h
+++ b/sgx/services4/srvkm/devices/sgx/mmu.h
@@ -1,53 +1,131 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title MMU Management
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements basic low level control of MMU.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _MMU_H_
#define _MMU_H_
#include "sgxinfokm.h"
+/*
+******************************************************************************
+ FUNCTION: MMU_Initialise
+
+ PURPOSE: Initialise the mmu module.
+
+ PARAMETERS: None
+ RETURNS: PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR
MMU_Initialise (PVRSRV_DEVICE_NODE *psDeviceNode, MMU_CONTEXT **ppsMMUContext, IMG_DEV_PHYADDR *psPDDevPAddr);
+/*
+******************************************************************************
+ FUNCTION: MMU_Finalise
+
+ PURPOSE: Finalise the mmu module, deallocate all resources.
+
+ PARAMETERS: None.
+ RETURNS: None.
+******************************************************************************/
IMG_VOID
MMU_Finalise (MMU_CONTEXT *psMMUContext);
+/*
+******************************************************************************
+ FUNCTION: MMU_InsertHeap
+
+ PURPOSE: Inserts shared heap into the specified context
+ from the kernel context
+
+ PARAMETERS: None.
+ RETURNS: None.
+******************************************************************************/
IMG_VOID
MMU_InsertHeap(MMU_CONTEXT *psMMUContext, MMU_HEAP *psMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_Create
+
+ PURPOSE: Create an mmu device.
+
+ PARAMETERS: In: psMMUContext -
+ In: psDevArena -
+ Out: ppsVMArena
+ RETURNS: MMU_HEAP
+******************************************************************************/
MMU_HEAP *
MMU_Create (MMU_CONTEXT *psMMUContext,
DEV_ARENA_DESCRIPTOR *psDevArena,
RA_ARENA **ppsVMArena,
PDUMP_MMU_ATTRIB **ppsMMUAttrib);
+/*
+******************************************************************************
+ FUNCTION: MMU_Delete
+
+ PURPOSE: Delete an mmu device.
+
+ PARAMETERS: In: pMMUHeap - The mmu to delete.
+ RETURNS:
+******************************************************************************/
IMG_VOID
MMU_Delete (MMU_HEAP *pMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_Alloc
+ PURPOSE: Allocate space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to allocate on.
+ In: uSize - Size in bytes to allocate.
+ Out: pActualSize - If non null receives actual size allocated.
+ In: uFlags - Allocation flags.
+ In: uDevVAddrAlignment - Required alignment.
+ Out: pDevVAddr - Receives base address of allocation.
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failure
+******************************************************************************/
IMG_BOOL
MMU_Alloc (MMU_HEAP *pMMUHeap,
IMG_SIZE_T uSize,
@@ -56,17 +134,60 @@ MMU_Alloc (MMU_HEAP *pMMUHeap,
IMG_UINT32 uDevVAddrAlignment,
IMG_DEV_VIRTADDR *pDevVAddr);
+/*
+******************************************************************************
+ FUNCTION: MMU_Free
+ PURPOSE: Frees space in an mmu's virtual address space.
+ PARAMETERS: In: pMMUHeap - MMU to free on.
+ In: DevVAddr - Base address of allocation.
+ RETURNS: IMG_TRUE - Success
+ IMG_FALSE - Failure
+******************************************************************************/
IMG_VOID
MMU_Free (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
IMG_UINT32 ui32Size);
+/*
+******************************************************************************
+ FUNCTION: MMU_Enable
+
+ PURPOSE: Enable an mmu. Establishes pages tables and takes the mmu out
+ of bypass and waits for the mmu to acknowledge enabled.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Enable (MMU_HEAP *pMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_Disable
+
+ PURPOSE: Disable an mmu, takes the mmu into bypass.
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_Disable (MMU_HEAP *pMMUHeap);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapPages
+
+ PURPOSE: Create a mapping for a range of pages from a device physical
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to map.
+ In: uSize - size of memory range in bytes
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapPages (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
@@ -75,22 +196,131 @@ MMU_MapPages (MMU_HEAP *pMMUHeap,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapPagesSparse
+
+ PURPOSE: Create a mapping for a range of pages from a device physical
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: SysPAddr - the system physical address of the page to map.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: ui32MemFlags - page table flags.
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapPagesSparse (MMU_HEAP *pMMUHeap,
+ IMG_DEV_VIRTADDR DevVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+ FUNCTION: MMU_MapShadow
+
+ PURPOSE: Create a mapping for a range of pages from a CPU virtual
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: uByteSize - A page aligned mapping length in bytes.
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapShadow (MMU_HEAP * pMMUHeap,
IMG_DEV_VIRTADDR MapBaseDevVAddr,
- IMG_SIZE_T uByteSize,
+ IMG_SIZE_T uByteSize,
IMG_CPU_VIRTADDR CpuVAddr,
IMG_HANDLE hOSMemHandle,
IMG_DEV_VIRTADDR * pDevVAddr,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapShadowSparse
+
+ PURPOSE: Create a mapping for a range of pages from a CPU virtual
+ adddress to a specified device virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: MapBaseDevVAddr - A page aligned device virtual address
+ to start mapping from.
+ In: ui32ChunkSize - Size of the chunk (must be page multiple)
+ In: ui32NumVirtChunks - Number of virtual chunks
+ In: ui32NumPhysChunks - Number of physical chunks
+ In: pabMapChunk - Mapping array
+ In: CpuVAddr - A page aligned CPU virtual address.
+ In: hOSMemHandle - An alternative OS specific memory handle
+ for mapping RAM without a CPU virtual
+ address
+ Out: pDevVAddr - deprecated
+ In: hUniqueTag - A unique ID for use as a tag identifier
+ In: ui32MemFlags - page table flags.
+ RETURNS: None
+******************************************************************************/
+IMG_VOID
+MMU_MapShadowSparse (MMU_HEAP * pMMUHeap,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL * pabMapChunk,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR * pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
+/*
+******************************************************************************
+ FUNCTION: MMU_UnmapPages
+
+ PURPOSE: unmaps pages and invalidates virtual address.
+
+ PARAMETERS: In: psMMUHeap - the mmu.
+ In: sDevVAddr - the device virtual address.
+ In: ui32PageCount - page count.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_UnmapPages (MMU_HEAP *psMMUHeap,
IMG_DEV_VIRTADDR sDevVAddr,
IMG_UINT32 ui32PageCount,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_MapScatter
+
+ PURPOSE: Create a mapping for a list of pages to a specified device
+ virtual address.
+
+ PARAMETERS: In: pMMUHeap - the mmu.
+ In: DevVAddr - the device virtual address.
+ In: psSysAddr - the list of physical addresses of the pages to
+ map.
+ RETURNS: None
+******************************************************************************/
IMG_VOID
MMU_MapScatter (MMU_HEAP *pMMUHeap,
IMG_DEV_VIRTADDR DevVAddr,
@@ -100,55 +330,173 @@ MMU_MapScatter (MMU_HEAP *pMMUHeap,
IMG_HANDLE hUniqueTag);
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPhysPageAddr
+
+ PURPOSE: extracts physical address from MMU page tables
+
+ PARAMETERS: In: pMMUHeap - the mmu
+ PARAMETERS: In: sDevVPageAddr - the virtual address to extract physical
+ page mapping from
+ RETURNS: IMG_DEV_PHYADDR
+******************************************************************************/
IMG_DEV_PHYADDR
MMU_GetPhysPageAddr(MMU_HEAP *pMMUHeap, IMG_DEV_VIRTADDR sDevVPageAddr);
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPDDevPAddr
+
+ PURPOSE: returns PD given the MMU context (SGX to MMU API)
+
+ PARAMETERS: In: pMMUContext - the mmu
+ RETURNS: IMG_DEV_PHYADDR
+******************************************************************************/
IMG_DEV_PHYADDR
MMU_GetPDDevPAddr(MMU_CONTEXT *pMMUContext);
#ifdef SUPPORT_SGX_MMU_BYPASS
+/*
+******************************************************************************
+ FUNCTION: EnableHostAccess
+
+ PURPOSE: Enables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
EnableHostAccess (MMU_CONTEXT *psMMUContext);
+/*
+******************************************************************************
+ FUNCTION: DisableHostAccess
+
+ PURPOSE: Disables Host accesses to device memory, by passing the device
+ MMU address translation
+
+ PARAMETERS: In: psMMUContext
+ RETURNS: None
+******************************************************************************/
IMG_VOID
DisableHostAccess (MMU_CONTEXT *psMMUContext);
#endif
+/*
+******************************************************************************
+ FUNCTION: MMU_InvalidateDirectoryCache
+
+ PURPOSE: Invalidates the page directory cache
+
+ PARAMETERS: In: psDevInfo
+ RETURNS: None
+******************************************************************************/
IMG_VOID MMU_InvalidateDirectoryCache(PVRSRV_SGXDEV_INFO *psDevInfo);
-PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
+/*
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDAlloc
-IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
+ PURPOSE: Allocate a dummy Page Directory which causes all virtual
+ addresses to page fault.
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-PVRSRV_ERROR WorkaroundBRN22997Alloc(PVRSRV_DEVICE_NODE *psDeviceNode);
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS: PVRSRV_OK or error
+******************************************************************************/
+PVRSRV_ERROR MMU_BIFResetPDAlloc(PVRSRV_SGXDEV_INFO *psDevInfo);
-IMG_VOID WorkaroundBRN22997ReadHostPort(PVRSRV_SGXDEV_INFO *psDevInfo);
+/*
+******************************************************************************
+ FUNCTION: MMU_BIFResetPDFree
-IMG_VOID WorkaroundBRN22997Free(PVRSRV_DEVICE_NODE *psDeviceNode);
-#endif
+ PURPOSE: Free resources allocated in MMU_BIFResetPDAlloc.
+
+ PARAMETERS: In: psDevInfo - device info
+ RETURNS:
+******************************************************************************/
+IMG_VOID MMU_BIFResetPDFree(PVRSRV_SGXDEV_INFO *psDevInfo);
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
+/*
+******************************************************************************
+ FUNCTION: MMU_MapExtSystemCacheRegs
+
+ PURPOSE: maps external system cache control registers into SGX MMU
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
PVRSRV_ERROR MMU_MapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
-PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
-#endif
+/*
+******************************************************************************
+ FUNCTION: MMU_UnmapExtSystemCacheRegs
+ PURPOSE: unmaps external system cache control registers
+
+ PARAMETERS: In: psDeviceNode - device node
+ RETURNS:
+******************************************************************************/
+PVRSRV_ERROR MMU_UnmapExtSystemCacheRegs(PVRSRV_DEVICE_NODE *psDeviceNode);
+#endif /* #if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE) */
+
+/*
+******************************************************************************
+ FUNCTION: MMU_IsHeapShared
+
+ PURPOSE: Is this heap shared?
+ PARAMETERS: In: pMMU_Heap
+ RETURNS: true if heap is shared
+******************************************************************************/
IMG_BOOL MMU_IsHeapShared(MMU_HEAP* pMMU_Heap);
#if defined(FIX_HW_BRN_31620)
+/*
+******************************************************************************
+ FUNCTION: MMU_GetCacheFlushRange
+
+ PURPOSE: Gets device physical address of the mmu context.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: pui32RangeMask - Bit mask showing which PD cache
+ lines have changed
+ RETURNS: None
+******************************************************************************/
IMG_VOID MMU_GetCacheFlushRange(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPDPhysAddr
+
+ PURPOSE: Gets device physical address of the mmu contexts PD.
+
+ PARAMETERS: In: pMMUContext - the mmu context
+ Out: psDevPAddr - Address of PD
+ RETURNS: None
+******************************************************************************/
IMG_VOID MMU_GetPDPhysAddr(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
#endif
+IMG_VOID MMU_CheckFaultAddr(PVRSRV_SGXDEV_INFO *psDevInfo, IMG_UINT32 ui32PDDevPAddr, IMG_UINT32 ui32RegVal);
+
#if defined(PDUMP)
+/*
+******************************************************************************
+ FUNCTION: MMU_GetPDumpContextID
+
+ PURPOSE: translates device mem context to unique pdump identifier
+
+ PARAMETERS: In: hDevMemContext - device memory per-process context
+ RETURNS: context identifier used internally in pdump
+******************************************************************************/
IMG_UINT32 MMU_GetPDumpContextID(IMG_HANDLE hDevMemContext);
-#endif
+#endif /* #ifdef PDUMP */
-#endif
+#endif /* #ifndef _MMU_H_ */
diff --git a/sgx/services4/srvkm/devices/sgx/pb.c b/sgx/services4/srvkm/devices/sgx/pb.c
index ab6523a..bcfe480 100644
--- a/sgx/services4/srvkm/devices/sgx/pb.c
+++ b/sgx/services4/srvkm/devices/sgx/pb.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Parameter Buffer management functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <stddef.h>
@@ -35,8 +51,8 @@
#include "pdump_km.h"
#include "sgxutils.h"
-#ifndef __linux__
-#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
+#if !defined(__linux__) && !defined(__QNXNTO__)
+#pragma message("FIXME: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
#endif
#include "lists.h"
@@ -50,6 +66,8 @@ static PVRSRV_PER_PROCESS_DATA *psPerProcCreateSharedPB = IMG_NULL;
static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy);
+/* override level pointer indirection */
+/* PRQA S 5102 12 */
IMG_EXPORT PVRSRV_ERROR
SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
@@ -108,7 +126,7 @@ SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
ppsSharedPBDescSubKernelMemInfos,
0);
-
+ /*not nulling pointer, out of scope*/
PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
@@ -173,15 +191,12 @@ ExitNotFound:
static PVRSRV_ERROR
SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
{
-
+ /*PVRSRV_STUB_PBDESC **ppsStubPBDesc;*/
IMG_UINT32 i;
PVRSRV_DEVICE_NODE *psDeviceNode;
psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
-
-
-
psStubPBDescIn->ui32RefCount--;
if (psStubPBDescIn->ui32RefCount == 0)
{
@@ -189,7 +204,6 @@ SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
{
-
PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
psStubPBDescIn->ppsSubKernelMemInfos[i]);
}
@@ -212,16 +226,16 @@ SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
sizeof(PVRSRV_STUB_PBDESC),
psStubPBDescIn,
0);
-
+ /*not nulling pointer, copy on stack*/
-
+ /* signal the microkernel to clear its sTAHWPBDesc and s3DHWPBDesc values in sTA3DCtl */
SGXCleanupRequest(psDeviceNode,
&sHWPBDescDevVAddr,
PVRSRV_CLEANUPCMD_PB,
CLEANUP_WITH_POLL);
}
return PVRSRV_OK;
-
+ /*return PVRSRV_ERROR_INVALID_PARAMS;*/
}
static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
@@ -281,7 +295,10 @@ SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_SGXDEV_INFO *psSGXDevInfo;
PRESMAN_ITEM psResItem;
-
+ /*
+ * The caller must have previously called SGXFindSharedPBDesc with
+ * bLockOnFailure set, and not managed to find a suitable shared PB.
+ */
if (psPerProcCreateSharedPB != psPerProc)
{
goto NoAdd;
@@ -309,7 +326,11 @@ SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
}
-
+ /*
+ * We make the caller think the add was successful,
+ * but return the existing shared PB desc rather than
+ * a new one.
+ */
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_PB_DESC,
psStubPBDesc,
@@ -324,7 +345,10 @@ SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
goto NoAddKeepPB;
}
-
+ /*
+ * The caller will unreference the PB desc after
+ * a successful add, so up the reference count.
+ */
psStubPBDesc->ui32RefCount++;
*phSharedPBDesc = (IMG_HANDLE)psResItem;
@@ -423,7 +447,8 @@ SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
}
psStubPBDesc->hDevCookie = hDevCookie;
-
+ /* Finally everything was prepared successfully so link the new
+ * PB in to place. */
List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
psStubPBDesc);
@@ -446,7 +471,7 @@ NoAdd:
sizeof(PVRSRV_STUB_PBDESC),
psStubPBDesc,
0);
-
+ /*not nulling pointer, out of scope*/
}
NoAddKeepPB:
@@ -464,3 +489,6 @@ NoAddKeepPB:
return eRet;
}
+/******************************************************************************
+ End of file (pb.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgx_bridge_km.h b/sgx/services4/srvkm/devices/sgx/sgx_bridge_km.h
index 8fb3002..8da3e9f 100644
--- a/sgx/services4/srvkm/devices/sgx/sgx_bridge_km.h
+++ b/sgx/services4/srvkm/devices/sgx/sgx_bridge_km.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX Bridge Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Header for the SGX Bridge code
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if !defined(__SGX_BRIDGE_KM_H__)
#define __SGX_BRIDGE_KM_H__
@@ -114,6 +131,47 @@ PVRSRV_ERROR DevInitSGXPart2KM(PVRSRV_PER_PROCESS_DATA *psPerProc,
SGX_BRIDGE_INIT_INFO *psInitInfo);
#endif
+/*!
+ * *****************************************************************************
+ * @brief Looks for a parameter buffer description that corresponds to
+ * a buffer of size ui32TotalPBSize, optionally taking the lock
+ * needed for SharedPBCreation on failure.
+ *
+ * Note if a PB Desc is found then its internal reference counter
+ * is automatically incremented. It is your responsability to call
+ * SGXUnrefSharedPBDesc to decrement this reference and free associated
+ * resources when you are done.
+ *
+ * If bLockOnFailure is set, and a suitable shared PB isn't found,
+ * an internal flag is set, allowing this process to create a
+ * shared PB. Any other process calling this function with
+ * bLockOnFailure set, will receive the return code
+ * PVRSRV_ERROR_PROCESSING_BLOCKED, indicating that it needs
+ * to retry the function call. The internal flag is cleared
+ * when this process creates a shared PB.
+ *
+ * Note: You are responsible for freeing the list returned in
+ * pppsSharedPBDescSubKernelMemInfos
+ * via OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ * sizeof(PVRSRV_KERNEL_MEM_INFO *)
+ * * ui32SharedPBDescSubKernelMemInfosCount,
+ * ppsSharedPBDescSubKernelMemInfos,
+ * NULL);
+ *
+ * @param[in] psPerProc
+ * @param[in] hDevCookie
+ * @param[in] bLockOnError
+ * @param[in] ui32TotalPBSize
+ * @param[in] phSharedPBDesc
+ * @param[out] ppsSharedPBDescKernelMemInfo
+ * @param[out] ppsHWPBDescKernelMemInfo
+ * @param[out] pppsSharedPBDescSubKernelMemInfos A list of integral sub meminfos.
+ * @param[out] ui32SharedPBDescSubKernelMemInfosCount
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
+/* disable QAC pointer level check for over 2 */
+/* PRQA S 5102++ */
IMG_IMPORT PVRSRV_ERROR
SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
@@ -127,9 +185,58 @@ SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount);
+/*!
+ * *****************************************************************************
+ * @brief Decrements the reference counter and frees all userspace resources
+ * associated with a SharedPBDesc.
+ *
+ * @param hSharedPBDesc
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc);
+/*!
+ * *****************************************************************************
+ * @brief Links a new SharedPBDesc into a kernel managed list that can
+ * then be queried by other clients.
+ *
+ * As a side affect this function also dissociates the SharedPBDesc
+ * from the calling process so that the memory won't be freed if the
+ * process dies/exits. (The kernel assumes responsability over the
+ * memory at the same time)
+ *
+ * As well as the psSharedPBDescKernelMemInfo you must also pass
+ * a complete list of other meminfos that are integral to the
+ * shared PB description. (Although the kernel doesn't have direct
+ * access to the shared PB desc it still needs to be able to
+ * clean up all the associated resources when it is no longer
+ * in use.)
+ *
+ * If the dissociation fails then all the memory associated with
+ * the psSharedPBDescKernelMemInfo and all entries in psKernelMemInfos
+ * will be freed by kernel services! Because of this, you are
+ * responsible for freeing the corresponding client meminfos _before_
+ * calling SGXAddSharedPBDescKM.
+ *
+ * This function will return an error unless a succesful call to
+ * SGXFindSharedPBDesc, with bLockOnFailure set, has been made.
+ *
+ * @param psPerProc
+ * @param hDevCookie
+ * @param psSharedPBDescKernelMemInfo
+ * @param psHWPBDescKernelMemInfo
+ * @param psBlockKernelMemInfo
+ * @param ui32TotalPBSize The size of the associated parameter buffer
+ * @param ppsSharedPBDescSubKernelMemInfos A list of other meminfos integral to
+ * the shared PB description.
+ * @param ui32SharedPBDescSubKernelMemInfosCount The number of entires in
+ * psKernelMemInfos
+ * @param sHWPBDescDevVAddr The device virtual address of the HWPBDesc
+ *
+ * @return PVRSRV_ERROR
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
@@ -144,6 +251,16 @@ SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_DEV_VIRTADDR sHWPBDescDevVAddr);
+/*!
+ * *****************************************************************************
+ * @brief Gets device information that is not intended to be passed
+ on beyond the srvclient libs.
+ *
+ * @param[in] hDevCookie
+ * @param[out] psSGXInternalDevInfo
+ *
+ * @return
+ ********************************************************************************/
IMG_IMPORT PVRSRV_ERROR
SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
#if defined (SUPPORT_SID_INTERFACE)
@@ -156,5 +273,8 @@ SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
}
#endif
-#endif
+#endif /* __SGX_BRIDGE_KM_H__ */
+/******************************************************************************
+ End of file (sgx_bridge_km.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxconfig.h b/sgx/services4/srvkm/devices/sgx/sgxconfig.h
index dddc6f5..dc024bc 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxconfig.h
+++ b/sgx/services4/srvkm/devices/sgx/sgxconfig.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title device configuration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __SGXCONFIG_H__
#define __SGXCONFIG_H__
@@ -41,6 +57,14 @@
#define SGX_KERNEL_DATA_HEAP_OFFSET 0x00000000
#endif
+#if !defined(ION_HEAP_SIZE) && defined(SUPPORT_ION)
+ /* Default the Ion heap to 16MB */
+ #define ION_HEAP_SIZE 0x01000000
+#else
+ #define ION_HEAP_SIZE 0
+#endif
+
+
#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 32
#if defined(FIX_HW_BRN_31620)
#if defined(SGX_FEATURE_2D_HARDWARE)
@@ -51,10 +75,20 @@
#define SGX_GENERAL_HEAP_BASE 0x08000000
#define SGX_GENERAL_HEAP_SIZE (0xB8000000-0x00001000)
-
+ /*
+ * For hybrid PB we have to split virtual PB range between the shared
+ * PB and percontext PB due to the fact we only have one heap config
+ * per device.
+ * If hybrid PB is enabled we split the space acording to HYBRID_SHARED_PB_SIZE.
+ * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+ * remainder is the size of the percontext PB.
+ * If hybrid PB is not enabled then we still create both heaps (helps keep
+ * the code clean) and define the size of the unused one to 0
+ */
+
#define SGX_3DPARAMETERS_HEAP_SIZE 0x10000000
-
+ /* By default we split the PB 50/50 */
#if !defined(HYBRID_SHARED_PB_SIZE)
#define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
#endif
@@ -76,10 +110,10 @@
#endif
#define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0xC0000000
-
+ /* Size is defiend above */
#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
-
+ /* Size is defiend above */
#define SGX_TADATA_HEAP_BASE 0xD0000000
#define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
@@ -99,21 +133,17 @@
#define SGX_KERNEL_DATA_HEAP_BASE (0xF0000000+SGX_KERNEL_DATA_HEAP_OFFSET)
#define SGX_KERNEL_DATA_HEAP_SIZE (0x03000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
-
+ /* Actual Pixel and Vertex shared heaps sizes may be reduced by
+ * override - see SGX_USE_CODE_SEGMENT_RANGE_BITS.*/
#define SGX_PIXELSHADER_HEAP_BASE 0xF4000000
#define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
#define SGX_VERTEXSHADER_HEAP_BASE 0xFC000000
#define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
-#else
+#else /* FIX_HW_BRN_31620 */
#if defined(SGX_FEATURE_2D_HARDWARE)
#define SGX_2D_HEAP_BASE 0x00100000
#define SGX_2D_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
- #else
- #if defined(FIX_HW_BRN_26915)
- #define SGX_CGBUFFER_HEAP_BASE 0x00100000
- #define SGX_CGBUFFER_HEAP_SIZE (0x08000000-0x00100000-0x00001000)
- #endif
#endif
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
@@ -121,13 +151,51 @@
#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x08000000-0x00001000)
#endif
- #define SGX_GENERAL_HEAP_BASE 0x10000000
- #define SGX_GENERAL_HEAP_SIZE (0xC2000000-0x00001000)
+ #if !defined(SUPPORT_MEMORY_TILING)
+ #if defined (SUPPORT_ION)
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xC2000000-ION_HEAP_SIZE-0x00001000)
+
+ #define SGX_ION_HEAP_BASE (SGX_GENERAL_HEAP_BASE+SGX_GENERAL_HEAP_SIZE+0x00001000)
+ #define SGX_ION_HEAP_SIZE (ION_HEAP_SIZE-0x00001000)
+ #else
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xC2000000-0x00001000)
+ #endif
+ #else
+ #include <sgx_msvdx_defs.h>
+ /* Create heaps with memory tiling enabled.
+ * SGX HW limit is 10 heaps.
+ */
+ /* Tiled heap space is taken from general heap */
+ #define SGX_GENERAL_HEAP_BASE 0x10000000
+ #define SGX_GENERAL_HEAP_SIZE (0xB5000000-0x00001000)
+
+ #define SGX_VPB_TILED_HEAP_STRIDE TILING_TILE_STRIDE_2K
+ #define SGX_VPB_TILED_HEAP_BASE 0xC5000000
+ #define SGX_VPB_TILED_HEAP_SIZE (0x0D000000-0x00001000)
+
+ /* Check tiled heap base alignment */
+ #if((SGX_VPB_TILED_HEAP_BASE & SGX_BIF_TILING_ADDR_INV_MASK) != 0)
+ #error "sgxconfig.h: SGX_VPB_TILED_HEAP has insufficient alignment"
+ #endif
+
+ #endif /* SUPPORT_MEMORY_TILING */
+
+ /*
+ * For hybrid PB we have to split virtual PB range between the shared
+ * PB and percontext PB due to the fact we only have one heap config
+ * per device.
+ * If hybrid PB is enabled we split the space acording to HYBRID_SHARED_PB_SIZE.
+ * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+ * remainder is the size of the percontext PB.
+ * If hybrid PB is not enabled then we still create both heaps (helps keep
+ * the code clean) and define the size of the unused one to 0
+ */
-
#define SGX_3DPARAMETERS_HEAP_SIZE 0x10000000
-
+ /* By default we split the PB 50/50 */
#if !defined(HYBRID_SHARED_PB_SIZE)
#define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
#endif
@@ -149,10 +217,10 @@
#endif
#define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0xD2000000
-
+ /* Size is defiend above */
#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
-
+ /* Size is defiend above */
#define SGX_TADATA_HEAP_BASE 0xE2000000
#define SGX_TADATA_HEAP_SIZE (0x0D000000-0x00001000)
@@ -172,16 +240,17 @@
#define SGX_KERNEL_DATA_HEAP_BASE (0xF4000000+SGX_KERNEL_DATA_HEAP_OFFSET)
#define SGX_KERNEL_DATA_HEAP_SIZE (0x05000000-(0x00001000+SGX_KERNEL_DATA_HEAP_OFFSET))
-
+ /* Actual Pixel and Vertex shared heaps sizes may be reduced by
+ * override - see SGX_USE_CODE_SEGMENT_RANGE_BITS.*/
#define SGX_PIXELSHADER_HEAP_BASE 0xF9000000
#define SGX_PIXELSHADER_HEAP_SIZE (0x05000000-0x00001000)
#define SGX_VERTEXSHADER_HEAP_BASE 0xFE000000
#define SGX_VERTEXSHADER_HEAP_SIZE (0x02000000-0x00001000)
-#endif
-
+#endif /* FIX_HW_BRN_31620 */
+ /* signal we've identified the core by the build */
#define SGX_CORE_IDENTIFIED
-#endif
+#endif /* SGX_FEATURE_ADDRESS_SPACE_SIZE == 32 */
#if SGX_FEATURE_ADDRESS_SPACE_SIZE == 28
@@ -190,18 +259,38 @@
#define SGX_GENERAL_MAPPING_HEAP_SIZE (0x01800000-0x00001000-0x00001000)
#define SGX_GENERAL_HEAP_BASE 0x01800000
-// #define SGX_GENERAL_HEAP_SIZE (0x07000000-0x00001000)
- #define SGX_GENERAL_HEAP_SIZE (0x0A000000-0x00001000)
+ #define SGX_GENERAL_HEAP_SIZE (0x07000000-ION_HEAP_SIZE-0x00001000)
#else
#define SGX_GENERAL_HEAP_BASE 0x00001000
-// #define SGX_GENERAL_HEAP_SIZE (0x08800000-0x00001000-0x00001000)
- #define SGX_GENERAL_HEAP_SIZE (0x0B800000-0x00001000-0x00001000)
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
+ #define SGX_GENERAL_HEAP_SIZE (0x0B800000-ION_HEAP_SIZE-0x00001000-0x00001000)
+#else
+ #define SGX_GENERAL_HEAP_SIZE (0x08800000-ION_HEAP_SIZE-0x00001000-0x00001000)
#endif
-
-// #define SGX_3DPARAMETERS_HEAP_SIZE 0x04000000
+#endif
+
+#if defined(SUPPORT_ION)
+ #define SGX_ION_HEAP_BASE (SGX_GENERAL_HEAP_BASE+SGX_GENERAL_HEAP_SIZE+0x00001000)
+ #define SGX_ION_HEAP_SIZE (ION_HEAP_SIZE-0x00001000)
+#endif
+ /*
+ * For hybrid PB we have to split virtual PB range between the shared
+ * PB and percontext PB due to the fact we only have one heap config
+ * per device.
+ * If hybrid PB is enabled we split the space acording to HYBRID_SHARED_PB_SIZE.
+ * i.e. HYBRID_SHARED_PB_SIZE defines the size of the shared PB and the
+ * remainder is the size of the percontext PB.
+ * If hybrid PB is not enabled then we still create both heaps (helps keep
+ * the code clean) and define the size of the unused one to 0
+ */
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
#define SGX_3DPARAMETERS_HEAP_SIZE 0x01000000
-
+#else
+ #define SGX_3DPARAMETERS_HEAP_SIZE 0x04000000
+#endif
+
+ /* By default we split the PB 50/50 */
#if !defined(HYBRID_SHARED_PB_SIZE)
#define HYBRID_SHARED_PB_SIZE (SGX_3DPARAMETERS_HEAP_SIZE >> 1)
#endif
@@ -222,11 +311,16 @@
#endif
#endif
-// #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x08800000
+#if defined(SUPPORT_LARGE_GENERAL_HEAP)
#define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x0B800000
+#else
+ #define SGX_SHARED_3DPARAMETERS_HEAP_BASE 0x08800000
+#endif
+
+ /* Size is defined above */
#define SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE (SGX_SHARED_3DPARAMETERS_HEAP_BASE + SGX_SHARED_3DPARAMETERS_SIZE)
-
+ /* Size is defined above */
#define SGX_TADATA_HEAP_BASE 0x0C800000
#define SGX_TADATA_HEAP_SIZE (0x01000000-0x00001000)
@@ -252,15 +346,20 @@
#define SGX_VERTEXSHADER_HEAP_BASE 0x0FC00000
#define SGX_VERTEXSHADER_HEAP_SIZE (0x00200000-0x00001000)
-
+ /* signal we've identified the core by the build */
#define SGX_CORE_IDENTIFIED
-#endif
+#endif /* SGX_FEATURE_ADDRESS_SPACE_SIZE == 28 */
#if !defined(SGX_CORE_IDENTIFIED)
#error "sgxconfig.h: ERROR: unspecified SGX Core version"
#endif
+/*********************************************************************************
+ *
+ * SGX_PDSPIXEL_CODEDATA_HEAP_BASE + 64MB range must include PDSVERTEX_CODEDATA and KERNEL_CODE heaps
+ *
+ ********************************************************************************/
#if !defined (SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE)
#if ((SGX_KERNEL_CODE_HEAP_BASE + SGX_KERNEL_CODE_HEAP_SIZE - SGX_PDSPIXEL_CODEDATA_HEAP_BASE) > 0x4000000)
#error "sgxconfig.h: ERROR: SGX_KERNEL_CODE_HEAP_BASE out of range of SGX_PDSPIXEL_CODEDATA_HEAP_BASE"
@@ -271,18 +370,33 @@
#endif
#endif
+/*********************************************************************************
+ *
+ * The General Mapping heap must be within the 2D requestor range of the 2D heap base
+ *
+ ********************************************************************************/
#if defined(SGX_FEATURE_2D_HARDWARE) && defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
#if ((SGX_GENERAL_MAPPING_HEAP_BASE + SGX_GENERAL_MAPPING_HEAP_SIZE - SGX_2D_HEAP_BASE) >= EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK)
#error "sgxconfig.h: ERROR: SGX_GENERAL_MAPPING_HEAP inaccessable by 2D requestor"
#endif
#endif
+/*********************************************************************************
+ *
+ * The kernel code heap base must be aligned to a USSE code page
+ *
+ ********************************************************************************/
#if defined (EURASIA_USE_CODE_PAGE_SIZE)
#if ((SGX_KERNEL_CODE_HEAP_BASE & (EURASIA_USE_CODE_PAGE_SIZE - 1)) != 0)
#error "sgxconfig.h: ERROR: Kernel code heap base misalignment"
#endif
#endif
+/*********************************************************************************
+ *
+ * Heap overlap check
+ *
+ ********************************************************************************/
#if defined(SGX_FEATURE_2D_HARDWARE)
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
#if ((SGX_2D_HEAP_BASE + SGX_2D_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
@@ -293,18 +407,6 @@
#error "sgxconfig.h: ERROR: SGX_2D_HEAP overlaps SGX_GENERAL_HEAP_BASE"
#endif
#endif
-#else
- #if defined(FIX_HW_BRN_26915)
- #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
- #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_MAPPING_HEAP_BASE)
- #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_MAPPING_HEAP"
- #endif
- #else
- #if ((SGX_CGBUFFER_HEAP_BASE + SGX_CGBUFFER_HEAP_SIZE) >= SGX_GENERAL_HEAP_BASE)
- #error "sgxconfig.h: ERROR: SGX_CGBUFFER_HEAP overlaps SGX_GENERAL_HEAP_BASE"
- #endif
- #endif
- #endif
#endif
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
@@ -319,8 +421,22 @@
#endif
#endif
-#if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
- #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+#if defined(SUPPORT_MEMORY_TILING)
+ #if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_VPB_TILED_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_VPB_TILED_HEAP"
+ #endif
+ #if ((SGX_VPB_TILED_HEAP_BASE + SGX_VPB_TILED_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_VPB_TILED_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
+#else
+ #if defined(SUPPORT_ION)
+ #if ((SGX_ION_HEAP_BASE + SGX_ION_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_ION_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
+ #endif
+ #if ((SGX_GENERAL_HEAP_BASE + SGX_GENERAL_HEAP_SIZE) >= SGX_SHARED_3DPARAMETERS_HEAP_BASE)
+ #error "sgxconfig.h: ERROR: SGX_GENERAL_HEAP overlaps SGX_3DPARAMETERS_HEAP"
+ #endif
#endif
#if (((SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE + SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE) >= SGX_TADATA_HEAP_BASE) && (SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE > 0))
@@ -359,5 +475,8 @@
#error "sgxconfig.h: ERROR: SGX_VERTEXSHADER_HEAP_BASE size cause wraparound"
#endif
-#endif
+#endif /* __SGXCONFIG_H__ */
+/*****************************************************************************
+ End of file (sgxconfig.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxinfokm.h b/sgx/services4/srvkm/devices/sgx/sgxinfokm.h
index 55bc9e4..af00041 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxinfokm.h
+++ b/sgx/services4/srvkm/devices/sgx/sgxinfokm.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title SGX kernel services structues/functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Structures and inline functions for KM services component
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __SGXINFOKM_H__
#define __SGXINFOKM_H__
@@ -38,11 +54,23 @@
extern "C" {
#endif
+/****************************************************************************/
+/* kernel only defines: */
+/****************************************************************************/
+/* SGXDeviceMap Flag defines */
#define SGX_HOSTPORT_PRESENT 0x00000001UL
+/*
+ SGX PDUMP register bank name (prefix)
+*/
#define SGX_PDUMPREG_NAME "SGXREG"
+/****************************************************************************/
+/* kernel only structures: */
+/****************************************************************************/
+
+/*Forward declaration*/
typedef struct _PVRSRV_STUB_PBDESC_ PVRSRV_STUB_PBDESC;
@@ -58,106 +86,106 @@ typedef struct _PVRSRV_SGXDEV_INFO_
IMG_UINT32 ui32CoreConfig;
IMG_UINT32 ui32CoreFlags;
-
+ /* Kernel mode linear address of device registers */
IMG_PVOID pvRegsBaseKM;
#if defined(SGX_FEATURE_HOST_PORT)
-
+ /* Kernel mode linear address of host port */
IMG_PVOID pvHostPortBaseKM;
-
+ /* HP size */
IMG_UINT32 ui32HPSize;
-
+ /* HP syspaddr */
IMG_SYS_PHYADDR sHPSysPAddr;
#endif
-
+ /* FIXME: The alloc for this should go through OSAllocMem in future */
IMG_HANDLE hRegMapping;
-
+ /* System physical address of device registers*/
IMG_SYS_PHYADDR sRegsPhysBase;
-
+ /* Register region size in bytes */
IMG_UINT32 ui32RegSize;
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
+ /* external system cache register region size in bytes */
IMG_UINT32 ui32ExtSysCacheRegsSize;
-
+ /* external system cache register device relative physical address */
IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
-
+ /* ptr to page table */
IMG_UINT32 *pui32ExtSystemCacheRegsPT;
-
+ /* handle to page table alloc/mapping */
IMG_HANDLE hExtSystemCacheRegsPTPageOSMemHandle;
-
+ /* sys phys addr of PT */
IMG_SYS_PHYADDR sExtSystemCacheRegsPTSysPAddr;
#endif
-
+ /* SGX clock speed */
IMG_UINT32 ui32CoreClockSpeed;
IMG_UINT32 ui32uKernelTimerClock;
+ IMG_BOOL bSGXIdle;
PVRSRV_STUB_PBDESC *psStubPBDescListKM;
-
+ /* kernel memory context info */
IMG_DEV_PHYADDR sKernelPDDevPAddr;
+ IMG_UINT32 ui32HeapCount; /*!< heap count */
IMG_VOID *pvDeviceMemoryHeap;
- PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo;
- PVRSRV_SGX_KERNEL_CCB *psKernelCCB;
- PPVRSRV_SGX_CCB_INFO psKernelCCBInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo;
- PVRSRV_SGX_CCB_CTL *psKernelCCBCtl;
- PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo;
- IMG_UINT32 *pui32KernelCCBEventKicker;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBMemInfo; /*!< meminfo for CCB in device accessible memory */
+ PVRSRV_SGX_KERNEL_CCB *psKernelCCB; /*!< kernel mode linear address of CCB in device accessible memory */
+ PPVRSRV_SGX_CCB_INFO psKernelCCBInfo; /*!< CCB information structure */
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBCtlMemInfo; /*!< meminfo for CCB control in device accessible memory */
+ PVRSRV_SGX_CCB_CTL *psKernelCCBCtl; /*!< kernel mode linear address of CCB control in device accessible memory */
+ PPVRSRV_KERNEL_MEM_INFO psKernelCCBEventKickerMemInfo; /*!< meminfo for kernel CCB event kicker */
+ IMG_UINT32 *pui32KernelCCBEventKicker; /*!< kernel mode linear address of kernel CCB event kicker */
#if defined(PDUMP)
- IMG_UINT32 ui32KernelCCBEventKickerDumpVal;
-#endif
- PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo;
- IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX];
+ IMG_UINT32 ui32KernelCCBEventKickerDumpVal; /*!< pdump copy of the kernel CCB event kicker */
+#endif /* PDUMP */
+ PVRSRV_KERNEL_MEM_INFO *psKernelSGXMiscMemInfo; /*!< kernel mode linear address of SGX misc info buffer */
+ IMG_UINT32 aui32HostKickAddr[SGXMKIF_CMD_MAX]; /*!< ukernel host kick offests */
#if defined(SGX_SUPPORT_HWPROFILING)
PPVRSRV_KERNEL_MEM_INFO psKernelHWProfilingMemInfo;
#endif
- PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelHWPerfCBMemInfo; /*!< Meminfo for hardware performace circular buffer */
+ PPVRSRV_KERNEL_MEM_INFO psKernelTASigBufferMemInfo; /*!< Meminfo for TA signature buffer */
+ PPVRSRV_KERNEL_MEM_INFO psKernel3DSigBufferMemInfo; /*!< Meminfo for 3D signature buffer */
#if defined(FIX_HW_BRN_29702)
- PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelCFIMemInfo; /*!< Meminfo for cfi */
#endif
#if defined(FIX_HW_BRN_29823)
- PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelDummyTermStreamMemInfo; /*!< Meminfo for dummy terminate stream */
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
- PPVRSRV_KERNEL_MEM_INFO psKernelVDMSnapShotBufferMemInfo;
- PPVRSRV_KERNEL_MEM_INFO psKernelVDMCtrlStreamBufferMemInfo;
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMSnapShotBufferMemInfo; /*!< Meminfo for dummy snapshot buffer */
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMCtrlStreamBufferMemInfo; /*!< Meminfo for dummy control stream */
#endif
#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && \
defined(FIX_HW_BRN_33657) && defined(SUPPORT_SECURE_33657_FIX)
- PPVRSRV_KERNEL_MEM_INFO psKernelVDMStateUpdateBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelVDMStateUpdateBufferMemInfo; /*!< Meminfo for state update buffer */
#endif
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
- PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo;
+ PPVRSRV_KERNEL_MEM_INFO psKernelEDMStatusBufferMemInfo; /*!< Meminfo for EDM status buffer */
#endif
-#if defined(SGX_FEATURE_OVERLAPPED_SPM)
- PPVRSRV_KERNEL_MEM_INFO psKernelTmpRgnHeaderMemInfo;
-#endif
-
+ /* Client reference count */
IMG_UINT32 ui32ClientRefCount;
-
+ /* cache control word for micro kernel cache flush/invalidates */
IMG_UINT32 ui32CacheControl;
-
+ /* client-side build options */
IMG_UINT32 ui32ClientBuildOptions;
-
+ /* client-side microkernel structure sizes */
SGX_MISCINFO_STRUCT_SIZES sSGXStructSizes;
-
-
-
+ /*
+ if we don't preallocate the pagetables we must
+ insert newly allocated page tables dynamically
+ */
IMG_VOID *pvMMUContextList;
-
+ /* Copy of registry ForcePTOff entry */
IMG_BOOL bForcePTOff;
IMG_UINT32 ui32EDMTaskReg0;
@@ -172,10 +200,10 @@ typedef struct _PVRSRV_SGXDEV_INFO_
IMG_UINT32 ui32MasterClkGateStatusMask;
IMG_UINT32 ui32MasterClkGateStatus2Reg;
IMG_UINT32 ui32MasterClkGateStatus2Mask;
-#endif
+#endif /* SGX_FEATURE_MP */
SGX_INIT_SCRIPTS sScripts;
-
+ /* Members associated with dummy PD needed for BIF reset */
IMG_HANDLE hBIFResetPDOSMemHandle;
IMG_DEV_PHYADDR sBIFResetPDDevPAddr;
IMG_DEV_PHYADDR sBIFResetPTDevPAddr;
@@ -183,32 +211,22 @@ typedef struct _PVRSRV_SGXDEV_INFO_
IMG_UINT32 *pui32BIFResetPD;
IMG_UINT32 *pui32BIFResetPT;
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-
- IMG_HANDLE hBRN22997PTPageOSMemHandle;
- IMG_HANDLE hBRN22997PDPageOSMemHandle;
- IMG_DEV_PHYADDR sBRN22997PTDevPAddr;
- IMG_DEV_PHYADDR sBRN22997PDDevPAddr;
- IMG_UINT32 *pui32BRN22997PT;
- IMG_UINT32 *pui32BRN22997PD;
- IMG_SYS_PHYADDR sBRN22997SysPAddr;
-#endif
#if defined(SUPPORT_HW_RECOVERY)
-
+ /* Timeout callback handle */
IMG_HANDLE hTimer;
-
+ /* HW recovery Time stamp */
IMG_UINT32 ui32TimeStamp;
#endif
-
+ /* Number of SGX resets */
IMG_UINT32 ui32NumResets;
-
+ /* host control */
PVRSRV_KERNEL_MEM_INFO *psKernelSGXHostCtlMemInfo;
SGXMKIF_HOST_CTL *psSGXHostCtl;
-
+ /* TA/3D control */
PVRSRV_KERNEL_MEM_INFO *psKernelSGXTA3DCtlMemInfo;
#if defined(FIX_HW_BRN_31272) || defined(FIX_HW_BRN_31780) || defined(FIX_HW_BRN_33920)
@@ -217,7 +235,7 @@ typedef struct _PVRSRV_SGXDEV_INFO_
IMG_UINT32 ui32Flags;
-
+ /* memory tiling range usage */
IMG_UINT32 ui32MemTilingUsage;
#if defined(PDUMP)
@@ -225,7 +243,7 @@ typedef struct _PVRSRV_SGXDEV_INFO_
#endif
#if defined(SUPPORT_SGX_MMU_DUMMY_PAGE)
-
+ /* SGX MMU dummy page details */
IMG_VOID *pvDummyPTPageCpuVAddr;
IMG_DEV_PHYADDR sDummyPTDevPAddr;
IMG_HANDLE hDummyPTPageOSMemHandle;
@@ -239,12 +257,12 @@ typedef struct _PVRSRV_SGXDEV_INFO_
IMG_UINT32 asSGXDevData[SGX_MAX_DEV_DATA];
#if defined(FIX_HW_BRN_31620)
-
+ /* Dummy page refs */
IMG_VOID *pvBRN31620DummyPageCpuVAddr;
IMG_HANDLE hBRN31620DummyPageOSMemHandle;
IMG_DEV_PHYADDR sBRN31620DummyPageDevPAddr;
-
+ /* Dummy PT refs */
IMG_VOID *pvBRN31620DummyPTCpuVAddr;
IMG_HANDLE hBRN31620DummyPTOSMemHandle;
IMG_DEV_PHYADDR sBRN31620DummyPTDevPAddr;
@@ -264,11 +282,13 @@ typedef struct _SGX_TIMING_INFORMATION_
IMG_UINT32 ui32uKernelFreq;
} SGX_TIMING_INFORMATION;
+/* FIXME Rename this structure to sg more generalised as it's been extended*/
+/* SGX device map */
typedef struct _SGX_DEVICE_MAP_
{
IMG_UINT32 ui32Flags;
-
+ /* Registers */
IMG_SYS_PHYADDR sRegsSysPBase;
IMG_CPU_PHYADDR sRegsCpuPBase;
IMG_CPU_VIRTADDR pvRegsCpuVBase;
@@ -280,7 +300,7 @@ typedef struct _SGX_DEVICE_MAP_
IMG_UINT32 ui32HPSize;
#endif
-
+ /* Local Device Memory Region: (if present) */
IMG_SYS_PHYADDR sLocalMemSysPBase;
IMG_DEV_PHYADDR sLocalMemDevPBase;
IMG_CPU_PHYADDR sLocalMemCpuPBase;
@@ -291,15 +311,15 @@ typedef struct _SGX_DEVICE_MAP_
IMG_DEV_PHYADDR sExtSysCacheRegsDevPBase;
#endif
-
+ /* device interrupt IRQ */
IMG_UINT32 ui32IRQ;
#if !defined(SGX_DYNAMIC_TIMING_INFO)
-
+ /* timing information*/
SGX_TIMING_INFORMATION sTimingInfo;
#endif
#if defined(PDUMP)
-
+ /* pdump memory region name */
IMG_CHAR *pszPDumpDevName;
#endif
} SGX_DEVICE_MAP;
@@ -321,15 +341,19 @@ struct _PVRSRV_STUB_PBDESC_
PVRSRV_STUB_PBDESC **ppsThis;
};
+/*!
+ ******************************************************************************
+ * CCB control structure for SGX
+ *****************************************************************************/
typedef struct _PVRSRV_SGX_CCB_INFO_
{
- PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo;
- PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo;
- SGXMKIF_COMMAND *psCommands;
- IMG_UINT32 *pui32WriteOffset;
- volatile IMG_UINT32 *pui32ReadOffset;
+ PVRSRV_KERNEL_MEM_INFO *psCCBMemInfo; /*!< meminfo for CCB in device accessible memory */
+ PVRSRV_KERNEL_MEM_INFO *psCCBCtlMemInfo; /*!< meminfo for CCB control in device accessible memory */
+ SGXMKIF_COMMAND *psCommands; /*!< linear address of the array of commands */
+ IMG_UINT32 *pui32WriteOffset; /*!< linear address of the write offset into array of commands */
+ volatile IMG_UINT32 *pui32ReadOffset; /*!< linear address of the read offset into array of commands */
#if defined(PDUMP)
- IMG_UINT32 ui32CCBDumpWOff;
+ IMG_UINT32 ui32CCBDumpWOff; /*!< for pdumping */
#endif
} PVRSRV_SGX_CCB_INFO;
@@ -371,9 +395,6 @@ typedef struct _SGX_BRIDGE_INIT_INFO_KM_
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
IMG_HANDLE hKernelEDMStatusBufferMemInfo;
#endif
-#if defined(SGX_FEATURE_OVERLAPPED_SPM)
- IMG_HANDLE hKernelTmpRgnHeaderMemInfo;
-#endif
IMG_UINT32 ui32EDMTaskReg0;
IMG_UINT32 ui32EDMTaskReg1;
@@ -381,7 +402,11 @@ typedef struct _SGX_BRIDGE_INIT_INFO_KM_
IMG_UINT32 ui32ClkGateStatusReg;
IMG_UINT32 ui32ClkGateStatusMask;
#if defined(SGX_FEATURE_MP)
-#endif
+// IMG_UINT32 ui32MasterClkGateStatusReg;
+// IMG_UINT32 ui32MasterClkGateStatusMask;
+// IMG_UINT32 ui32MasterClkGateStatus2Reg;
+// IMG_UINT32 ui32MasterClkGateStatus2Mask;
+#endif /* SGX_FEATURE_MP */
IMG_UINT32 ui32CacheControl;
@@ -406,7 +431,7 @@ typedef struct _SGX_CCB_KICK_KM_
IMG_UINT32 ui32NumDstSyncObjects;
IMG_HANDLE hKernelHWSyncListMemInfo;
-
+ /* DST syncs */
IMG_HANDLE *pahDstSyncHandles;
IMG_UINT32 ui32NumTAStatusVals;
@@ -425,11 +450,11 @@ typedef struct _SGX_CCB_KICK_KM_
IMG_BOOL bTerminateOrAbort;
#endif
-
+ /* CCB offset of data structure associated with this kick */
IMG_UINT32 ui32CCBOffset;
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST syncs */
IMG_UINT32 ui32NumTASrcSyncs;
IMG_HANDLE ahTASrcKernelSyncInfo[SGX_MAX_TA_SRC_SYNCS];
IMG_UINT32 ui32NumTADstSyncs;
@@ -437,12 +462,12 @@ typedef struct _SGX_CCB_KICK_KM_
IMG_UINT32 ui32Num3DSrcSyncs;
IMG_HANDLE ah3DSrcKernelSyncInfo[SGX_MAX_3D_SRC_SYNCS];
#else
-
+ /* SRC syncs */
IMG_UINT32 ui32NumSrcSyncs;
- IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS];
+ IMG_HANDLE ahSrcKernelSyncInfo[SGX_MAX_SRC_SYNCS_TA];
#endif
-
+ /* TA/3D dependency data */
IMG_BOOL bTADependency;
IMG_HANDLE hTA3DSyncInfo;
@@ -493,13 +518,13 @@ typedef struct _PVRSRV_2D_SGX_KICK_KM_
IMG_UINT32 ui32NumSrcSync;
IMG_HANDLE ahSrcSyncInfo[SGX_MAX_2D_SRC_SYNC_OPS];
-
+ /* need to be able to check reads and writes on dest, and update writes */
IMG_HANDLE hDstSyncInfo;
-
+ /* need to be able to check reads and writes on TA ops, and update writes */
IMG_HANDLE hTASyncInfo;
-
+ /* need to be able to check reads and writes on 2D ops, and update writes */
IMG_HANDLE h3DSyncInfo;
IMG_UINT32 ui32PDumpFlags;
@@ -507,9 +532,12 @@ typedef struct _PVRSRV_2D_SGX_KICK_KM_
IMG_UINT32 ui32CCBDumpWOff;
#endif
} PVRSRV_2D_SGX_KICK_KM, *PPVRSRV_2D_SGX_KICK_KM;
-#endif
-#endif
+#endif /* defined(SGX_FEATURE_2D_HARDWARE) */
+#endif /* #if defined(TRANSFER_QUEUE) */
+/****************************************************************************/
+/* kernel only functions prototypes */
+/****************************************************************************/
PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode);
IMG_VOID SGXOSTimer(IMG_VOID *pvData);
@@ -543,12 +571,18 @@ PVRSRV_ERROR SGXPostClockSpeedChange(IMG_HANDLE hDevHandle,
IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo);
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs);
+
PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode);
#if defined(SGX_DYNAMIC_TIMING_INFO)
IMG_VOID SysGetSGXTimingInformation(SGX_TIMING_INFORMATION *psSGXTimingInfo);
#endif
+/****************************************************************************/
+/* kernel only functions: */
+/****************************************************************************/
#if defined(NO_HARDWARE)
static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32StatusRegister,
@@ -570,5 +604,8 @@ static INLINE IMG_VOID NoHardwareGenerateEvent(PVRSRV_SGXDEV_INFO *psDevInfo,
}
#endif
-#endif
+#endif /* __SGXINFOKM_H__ */
+/*****************************************************************************
+ End of file (sgxinfokm.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxinit.c b/sgx/services4/srvkm/devices/sgx/sgxinit.c
index 0b7d074..b794321 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxinit.c
+++ b/sgx/services4/srvkm/devices/sgx/sgxinit.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific initialisation routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <stddef.h>
@@ -52,9 +68,26 @@
#include "lists.h"
#include "srvkm.h"
#include "ttrace.h"
-#define VAR(x) #x
-
+#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
+
+static const IMG_CHAR *SGXUKernelStatusString(IMG_UINT32 code)
+{
+ switch(code)
+ {
+#define MKTC_ST(x) \
+ case x: \
+ return #x;
+#include "sgx_ukernel_status_codes.h"
+ default:
+ return "(Unknown)";
+ }
+}
+
+#endif /* defined(PVRSRV_USSE_EDM_STATUS_DEBUG) */
+
+#define VAR(x) #x
+/* PRQA S 0881 11 */ /* ignore 'order of evaluation' warning */
#define CHECK_SIZE(NAME) \
{ \
if (psSGXStructSizes->ui32Sizeof_##NAME != psDevInfo->sSGXStructSizes.ui32Sizeof_##NAME) \
@@ -76,20 +109,37 @@ static
PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_HANDLE hDevMemContext);
-static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
- IMG_BOOL bDumpSGXRegs);
-
#if defined(PDUMP)
static
PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode);
#endif
+/*!
+*******************************************************************************
+
+ @Function SGXCommandComplete
+
+ @Description
+
+ SGX command complete handler
+
+ @Input psDeviceNode - SGX device node
+
+ @Return none
+
+******************************************************************************/
static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
{
#if defined(OS_SUPPORTS_IN_LISR)
if (OSInLISR(psDeviceNode->psSysData))
{
-
+ /*
+ * We shouldn't call SGXScheduleProcessQueuesKM in an
+ * LISR, as it may attempt to power up SGX.
+ * We assume that the LISR will schedule the MISR, which
+ * will test the following flag, and call
+ * SGXScheduleProcessQueuesKM if the flag is set.
+ */
psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
}
else
@@ -101,18 +151,47 @@ static IMG_VOID SGXCommandComplete(PVRSRV_DEVICE_NODE *psDeviceNode)
#endif
}
+/*!
+*******************************************************************************
+
+ @Function DeinitDevInfo
+
+ @Description
+
+ Deinits DevInfo
+
+ @Input none
+
+ @Return none
+
+******************************************************************************/
static IMG_UINT32 DeinitDevInfo(PVRSRV_SGXDEV_INFO *psDevInfo)
{
if (psDevInfo->psKernelCCBInfo != IMG_NULL)
{
-
-
+ /*
+ Free CCB info.
+ */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(PVRSRV_SGX_CCB_INFO), psDevInfo->psKernelCCBInfo, IMG_NULL);
}
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function InitDevInfo
+
+ @Description
+
+ Loads DevInfo
+
+ @Input psDeviceNode
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
PVRSRV_DEVICE_NODE *psDeviceNode,
#if defined (SUPPORT_SID_INTERFACE)
@@ -163,7 +242,7 @@ static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined(FIX_HW_BRN_29823)
psDevInfo->psKernelDummyTermStreamMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelDummyTermStreamMemInfo;
#endif
-#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31425)
+#if defined(SGX_FEATURE_VDM_CONTEXT_SWITCH) && defined(FIX_HW_BRN_31559)
psDevInfo->psKernelVDMSnapShotBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMSnapShotBufferMemInfo;
psDevInfo->psKernelVDMCtrlStreamBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelVDMCtrlStreamBufferMemInfo;
#endif
@@ -174,20 +253,19 @@ static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
psDevInfo->psKernelEDMStatusBufferMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelEDMStatusBufferMemInfo;
#endif
-#if defined(SGX_FEATURE_OVERLAPPED_SPM)
- psDevInfo->psKernelTmpRgnHeaderMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpRgnHeaderMemInfo;
-#endif
-#if defined(SGX_FEATURE_SPM_MODE_0)
- psDevInfo->psKernelTmpDPMStateMemInfo = (PVRSRV_KERNEL_MEM_INFO *)psInitInfo->hKernelTmpDPMStateMemInfo;
-#endif
-
+ /*
+ * Assign client-side build options for later verification
+ */
psDevInfo->ui32ClientBuildOptions = psInitInfo->ui32ClientBuildOptions;
-
+ /*
+ * Assign microkernel IF structure sizes for later verification
+ */
psDevInfo->sSGXStructSizes = psInitInfo->sSGXStructSizes;
-
-
+ /*
+ Setup the kernel version of the CCB control
+ */
eError = OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_SGX_CCB_INFO),
(IMG_VOID **)&psKernelCCBInfo, 0,
@@ -207,8 +285,9 @@ static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
psKernelCCBInfo->pui32ReadOffset = &psDevInfo->psKernelCCBCtl->ui32ReadOffset;
psDevInfo->psKernelCCBInfo = psKernelCCBInfo;
-
-
+ /*
+ Copy the USE code addresses for the host kick.
+ */
OSMemCopy(psDevInfo->aui32HostKickAddr, psInitInfo->aui32HostKickAddr,
SGXMKIF_CMD_MAX * sizeof(psDevInfo->aui32HostKickAddr[0]));
@@ -227,10 +306,10 @@ static PVRSRV_ERROR InitDevInfo(PVRSRV_PER_PROCESS_DATA *psPerProc,
psDevInfo->ui32MasterClkGateStatusMask = psInitInfo->ui32MasterClkGateStatusMask;
psDevInfo->ui32MasterClkGateStatus2Reg = psInitInfo->ui32MasterClkGateStatus2Reg;
psDevInfo->ui32MasterClkGateStatus2Mask = psInitInfo->ui32MasterClkGateStatus2Mask;
-#endif
+#endif /* SGX_FEATURE_MP */
-
+ /* Initialise Dev Data */
OSMemCopy(&psDevInfo->asSGXDevData, &psInitInfo->asInitDevData, sizeof(psDevInfo->asSGXDevData));
return PVRSRV_OK;
@@ -262,6 +341,15 @@ static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND
PDUMPREG(SGX_PDUMPREG_NAME, psComm->sWriteHWReg.ui32Offset, psComm->sWriteHWReg.ui32Value);
break;
}
+ case SGX_INIT_OP_READ_HW_REG:
+ {
+ OSReadHWReg(psDevInfo->pvRegsBaseKM, psComm->sReadHWReg.ui32Offset);
+#if defined(PDUMP)
+ PDUMPCOMMENT("SGXRunScript: Read HW reg operation");
+ PDumpRegRead(SGX_PDUMPREG_NAME, psComm->sReadHWReg.ui32Offset, PDUMP_FLAGS_CONTINUOUS);
+#endif
+ break;
+ }
#if defined(PDUMP)
case SGX_INIT_OP_PDUMP_HW_REG:
{
@@ -275,7 +363,7 @@ static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND
return PVRSRV_OK;
}
case SGX_INIT_OP_ILLEGAL:
-
+ /* FALLTHROUGH */
default:
{
PVR_DPF((PVR_DBG_ERROR,"SGXRunScript: PC %d: Illegal command: %d", ui32PC, psComm->eOp));
@@ -288,6 +376,93 @@ static PVRSRV_ERROR SGXRunScript(PVRSRV_SGXDEV_INFO *psDevInfo, SGX_INIT_COMMAND
return PVRSRV_ERROR_UNKNOWN_SCRIPT_OPERATION;
}
+#if defined(SUPPORT_MEMORY_TILING)
+static PVRSRV_ERROR SGX_AllocMemTilingRangeInt(PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_UINT32 ui32Start,
+ IMG_UINT32 ui32End,
+ IMG_UINT32 ui32TilingStride,
+ IMG_UINT32 *pui32RangeIndex)
+{
+ IMG_UINT32 i;
+ IMG_UINT32 ui32Offset;
+ IMG_UINT32 ui32Val;
+
+ /* HW supports 10 ranges */
+ for(i=0; i < SGX_BIF_NUM_TILING_RANGES; i++)
+ {
+ if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
+ {
+ /* mark in use */
+ psDevInfo->ui32MemTilingUsage |= 1U << i;
+ /* output range index if the caller wants it */
+ if(pui32RangeIndex != IMG_NULL)
+ {
+ *pui32RangeIndex = i;
+ }
+ goto RangeAllocated;
+ }
+ }
+
+ PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
+ return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
+
+RangeAllocated:
+
+ /* An improperly aligned range could cause BIF not to tile some memory which is intended to be tiled,
+ * or cause BIF to tile some memory which is not intended to be.
+ */
+ if(ui32Start & ~SGX_BIF_TILING_ADDR_MASK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range start (0x%08X) fails"
+ "alignment test", ui32Start));
+ }
+ if((ui32End + 0x00001000) & ~SGX_BIF_TILING_ADDR_MASK)
+ {
+ PVR_DPF((PVR_DBG_WARNING,"SGX_AllocMemTilingRangeInt: Tiling range end (0x%08X) fails"
+ "alignment test", ui32End));
+ }
+
+ ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
+
+ ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
+ | (((ui32End>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
+ | (((ui32Start>>SGX_BIF_TILING_ADDR_LSB) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
+ | (EUR_CR_BIF_TILE0_ENABLE << EUR_CR_BIF_TILE0_CFG_SHIFT);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+
+#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
+ ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
+
+ ui32Val = (((ui32End>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
+ | (((ui32Start>>SGX_BIF_TILING_EXT_ADDR_LSB) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
+
+ OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
+ PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
+#endif /* SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS */
+
+ return PVRSRV_OK;
+}
+
+#endif /* SUPPORT_MEMORY_TILING */
+
+/*!
+*******************************************************************************
+
+ @Function SGXInitialise
+
+ @Description
+
+ (client invoked) chip-reset and initialisation
+
+ @Input pvDeviceNode - device info. structure
+ @Input bHardwareRecovery - true if recovering powered hardware,
+ false if powering up
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bHardwareRecovery)
{
@@ -297,16 +472,17 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
static IMG_BOOL bFirstTime = IMG_TRUE;
#if defined(PDUMP)
IMG_BOOL bPDumpIsSuspended = PDumpIsSuspended();
-#endif
+#endif /* PDUMP */
#if defined(SGX_FEATURE_MP)
-
+ /* Slave core clocks must be enabled during reset */
#else
SGXInitClocks(psDevInfo, PDUMP_FLAGS_CONTINUOUS);
-#endif
-
+#endif /* SGX_FEATURE_MP */
-
+ /*
+ Part 1 of the initialisation script runs before resetting SGX.
+ */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 1\n");
eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart1, SGX_MAX_INIT_COMMANDS);
if (eError != PVRSRV_OK)
@@ -316,27 +492,33 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
}
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 1\n");
-
+ /* Reset the chip */
psDevInfo->ui32NumResets++;
- SGXReset(psDevInfo, bFirstTime || bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
+
+#if !defined(SGX_FEATURE_MP)
+ bHardwareRecovery |= bFirstTime;
+#endif /* SGX_FEATURE_MP */
+
+ SGXReset(psDevInfo, bHardwareRecovery, PDUMP_FLAGS_CONTINUOUS);
#if defined(EUR_CR_POWER)
#if defined(SGX531)
-
-
-
-
-
+ /*
+ Disable half the pipes.
+ 531 has 2 pipes within a 4 pipe framework, so
+ the 2 redundant pipes must be disabled even
+ though they do not exist.
+ */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 1);
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 1);
#else
-
+ /* set the default pipe count (all fully enabled) */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_POWER, 0);
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_POWER, 0);
#endif
#endif
-
+ /* Initialise the kernel CCB event kicker value */
*psDevInfo->pui32KernelCCBEventKicker = 0;
#if defined(PDUMP)
if (!bPDumpIsSuspended)
@@ -347,10 +529,42 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
sizeof(*psDevInfo->pui32KernelCCBEventKicker), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
}
-#endif
+#endif /* PDUMP */
-
+#if defined(SUPPORT_MEMORY_TILING)
+ {
+ /* Initialise EUR_CR_BIF_TILE registers for any tiling heaps */
+ DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDevInfo->pvDeviceMemoryHeap;
+ IMG_UINT32 i;
+
+ psDevInfo->ui32MemTilingUsage = 0;
+
+ for(i=0; i<psDevInfo->ui32HeapCount; i++)
+ {
+ if(psDeviceMemoryHeap[i].ui32XTileStride > 0)
+ {
+ /* Set up the HW control registers */
+ eError = SGX_AllocMemTilingRangeInt(
+ psDevInfo,
+ psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr,
+ psDeviceMemoryHeap[i].sDevVAddrBase.uiAddr
+ + psDeviceMemoryHeap[i].ui32HeapSize,
+ psDeviceMemoryHeap[i].ui32XTileStride,
+ NULL);
+ if(eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "Unable to allocate SGX BIF tiling range for heap: %s",
+ psDeviceMemoryHeap[i].pszName));
+ break;
+ }
+ }
+ }
+ }
+#endif
+ /*
+ Part 2 of the initialisation script runs after resetting SGX.
+ */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "SGX initialisation script part 2\n");
eError = SGXRunScript(psDevInfo, psDevInfo->sScripts.asInitCommandsPart2, SGX_MAX_INIT_COMMANDS);
if (eError != PVRSRV_OK)
@@ -360,7 +574,7 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
}
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "End of SGX initialisation script part 2\n");
-
+ /* Record the system timestamp for the microkernel */
psSGXHostCtl->ui32HostClock = OSClockus();
psSGXHostCtl->ui32InitStatus = 0;
@@ -373,7 +587,7 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
MAKEUNIQUETAG(psSGXHostCtlMemInfo));
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
"Initialise the microkernel\n");
-#endif
+#endif /* PDUMP */
#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
OSWriteMemoryBarrier();
@@ -386,13 +600,14 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
OSWriteHWReg(psDevInfo->pvRegsBaseKM,
SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0),
EUR_CR_EVENT_KICK_NOW_MASK);
-#endif
+#endif /* SGX_FEATURE_MULTI_EVENT_KICK */
OSMemoryBarrier();
#if defined(PDUMP)
-
-
+ /*
+ Dump the host kick.
+ */
if (!bPDumpIsSuspended)
{
#if defined(SGX_FEATURE_MULTI_EVENT_KICK)
@@ -408,13 +623,14 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelCCBEventKickerMemInfo));
PDUMPREG(SGX_PDUMPREG_NAME, SGX_MP_CORE_SELECT(EUR_CR_EVENT_KICK, 0), EUR_CR_EVENT_KICK_NOW_MASK);
-#endif
+#endif /* SGX_FEATURE_MULTI_EVENT_KICK */
}
-#endif
+#endif /* PDUMP */
#if !defined(NO_HARDWARE)
-
-
+ /*
+ Wait for the microkernel to finish initialising.
+ */
if (PollForValueKM(&psSGXHostCtl->ui32InitStatus,
PVRSRV_USSE_EDM_INIT_COMPLETE,
PVRSRV_USSE_EDM_INIT_COMPLETE,
@@ -423,13 +639,13 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_FALSE) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "SGXInitialise: Wait for uKernel initialisation failed"));
- #if !defined(FIX_HW_BRN_23281)
+
SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
- #endif
+
return PVRSRV_ERROR_RETRY;
}
-#endif
+#endif /* NO_HARDWARE */
#if defined(PDUMP)
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
@@ -441,14 +657,7 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMP_POLL_OPERATOR_EQUAL,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psSGXHostCtlMemInfo));
-#endif
-
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
-
-
-
- WorkaroundBRN22997ReadHostPort(psDevInfo);
-#endif
+#endif /* PDUMP */
PVR_ASSERT(psDevInfo->psKernelCCBCtl->ui32ReadOffset == psDevInfo->psKernelCCBCtl->ui32WriteOffset);
@@ -457,13 +666,27 @@ PVRSRV_ERROR SGXInitialise(PVRSRV_SGXDEV_INFO *psDevInfo,
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function SGXDeinitialise
+
+ @Description
+
+ (client invoked) chip-reset and deinitialisation
+
+ @Input hDevCookie - device info. handle
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
{
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *) hDevCookie;
PVRSRV_ERROR eError;
-
+ /* Did SGXInitialise map the SGX registers in? */
if (psDevInfo->pvRegsBaseKM == IMG_NULL)
{
return PVRSRV_OK;
@@ -480,6 +703,20 @@ PVRSRV_ERROR SGXDeinitialise(IMG_HANDLE hDevCookie)
}
+/*!
+*******************************************************************************
+
+ @Function DevInitSGXPart1
+
+ @Description
+
+ Reset and initialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
{
IMG_HANDLE hDevMemHeap = IMG_NULL;
@@ -491,7 +728,7 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap = psDeviceNode->sDevMemoryInfo.psDeviceMemoryHeap;
PVRSRV_ERROR eError;
-
+ /* pdump info about the core */
PDUMPCOMMENT("SGX Core Version Information: %s", SGX_CORE_FRIENDLY_NAME);
#if defined(SGX_FEATURE_MP)
@@ -500,7 +737,7 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
#else
PDUMPCOMMENT("SGX Multi-processor: %d TA cores, %d 3D cores", SGX_FEATURE_MP_CORE_COUNT_TA, SGX_FEATURE_MP_CORE_COUNT_3D);
#endif
- #endif
+ #endif /* SGX_FEATURE_MP */
#if (SGX_CORE_REV == 0)
PDUMPCOMMENT("SGX Core Revision Information: head RTL");
@@ -512,12 +749,12 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
PDUMPCOMMENT("SGX System Level Cache is present\r\n");
#if defined(SGX_BYPASS_SYSTEM_CACHE)
PDUMPCOMMENT("SGX System Level Cache is bypassed\r\n");
- #endif
- #endif
+ #endif /* SGX_BYPASS_SYSTEM_CACHE */
+ #endif /* SGX_FEATURE_SYSTEM_CACHE */
PDUMPCOMMENT("SGX Initialisation Part 1");
-
+ /* Allocate device control block */
if(OSAllocMem( PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_SGXDEV_INFO),
(IMG_VOID **)&psDevInfo, IMG_NULL,
@@ -528,17 +765,18 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
}
OSMemSet (psDevInfo, 0, sizeof(PVRSRV_SGXDEV_INFO));
-
+ /* setup info from jdisplayconfig.h (variations controlled by build) */
psDevInfo->eDeviceType = DEV_DEVICE_TYPE;
psDevInfo->eDeviceClass = DEV_DEVICE_CLASS;
-
+ /* Store the devinfo as its needed by dynamically enumerated systems called from BM */
psDeviceNode->pvDevice = (IMG_PVOID)psDevInfo;
-
+ /* get heap info from the devnode */
+ psDevInfo->ui32HeapCount = psDeviceNode->sDevMemoryInfo.ui32HeapCount;
psDevInfo->pvDeviceMemoryHeap = (IMG_VOID*)psDeviceMemoryHeap;
-
+ /* create the kernel memory context */
hKernelDevMemContext = BM_CreateContext(psDeviceNode,
&sPDDevPAddr,
IMG_NULL,
@@ -551,7 +789,7 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
-
+ /* create the kernel, shared and shared_exported heaps */
for(i=0; i<psDeviceNode->sDevMemoryInfo.ui32HeapCount; i++)
{
switch(psDeviceMemoryHeap[i].DevMemHeapType)
@@ -560,14 +798,15 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
case DEVICE_MEMORY_HEAP_SHARED:
case DEVICE_MEMORY_HEAP_SHARED_EXPORTED:
{
-
+ /* Shared PB heap could be zero size */
if (psDeviceMemoryHeap[i].ui32HeapSize > 0)
{
hDevMemHeap = BM_CreateHeap (hKernelDevMemContext,
&psDeviceMemoryHeap[i]);
-
-
-
+ /*
+ in the case of kernel context heaps just store
+ the heap handle in the heap info structure
+ */
psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
}
break;
@@ -577,7 +816,7 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
#if defined(PDUMP)
if(hDevMemHeap)
{
-
+ /* set up the MMU pdump info */
psDevInfo->sMMUAttrib = *((BM_HEAP*)hDevMemHeap)->psMMUAttrib;
}
#endif
@@ -591,6 +830,23 @@ static PVRSRV_ERROR DevInitSGXPart1 (IMG_VOID *pvDeviceNode)
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function SGXGetInfoForSrvinitKM
+
+ @Description
+
+ Get SGX related information necessary for initilisation server
+
+ @Input hDevHandle - device handle
+ psInitInfo - pointer to structure for returned information
+
+ @Output psInitInfo - pointer to structure containing returned information
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, PVRSRV_HEAP_INFO_KM *pasHeapInfo, IMG_DEV_PHYADDR *psPDDevPAddr)
@@ -625,6 +881,20 @@ PVRSRV_ERROR SGXGetInfoForSrvinitKM(IMG_HANDLE hDevHandle, SGX_BRIDGE_INFO_FOR_S
return eError;
}
+/*!
+*******************************************************************************
+
+ @Function DevInitSGXPart2KM
+
+ @Description
+
+ Reset and initialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevHandle,
@@ -645,8 +915,9 @@ PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
psDeviceNode = (PVRSRV_DEVICE_NODE *)hDevHandle;
psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
-
-
+ /*
+ Init devinfo
+ */
eError = InitDevInfo(psPerProc, psDeviceNode, psInitInfo);
if (eError != PVRSRV_OK)
{
@@ -663,14 +934,14 @@ PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
return PVRSRV_ERROR_INIT_FAILURE;
}
-
+ /* Registers already mapped? */
if (psSGXDeviceMap->pvRegsCpuVBase)
{
psDevInfo->pvRegsBaseKM = psSGXDeviceMap->pvRegsCpuVBase;
}
else
{
-
+ /* Map Regs */
psDevInfo->pvRegsBaseKM = OSMapPhysToLin(psSGXDeviceMap->sRegsCpuPBase,
psSGXDeviceMap->ui32RegsSize,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
@@ -688,7 +959,7 @@ PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined(SGX_FEATURE_HOST_PORT)
if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
{
-
+ /* Map Host Port */
psDevInfo->pvHostPortBaseKM = OSMapPhysToLin(psSGXDeviceMap->sHPCpuPBase,
psSGXDeviceMap->ui32HPSize,
PVRSRV_HAP_KERNEL_ONLY|PVRSRV_HAP_UNCACHED,
@@ -701,21 +972,21 @@ PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
psDevInfo->ui32HPSize = psSGXDeviceMap->ui32HPSize;
psDevInfo->sHPSysPAddr = psSGXDeviceMap->sHPSysPBase;
}
-#endif
+#endif/* #ifdef SGX_FEATURE_HOST_PORT */
#if defined (SYS_USING_INTERRUPTS)
-
+ /* Set up ISR callback information. */
psDeviceNode->pvISRData = psDeviceNode;
-
+ /* ISR handler address was set up earlier */
PVR_ASSERT(psDeviceNode->pfnDeviceISR == SGX_ISRHandler);
-#endif
+#endif /* SYS_USING_INTERRUPTS */
-
+ /* Prevent the microkernel being woken up before there is something to do. */
psDevInfo->psSGXHostCtl->ui32PowerStatus |= PVRSRV_USSE_EDM_POWMAN_NO_WORK;
eDefaultPowerState = PVRSRV_DEV_POWER_STATE_OFF;
-
+ /* Register the device with the power manager. */
eError = PVRSRVRegisterPowerDevice (psDeviceNode->sDevId.ui32DeviceIndex,
&SGXPrePowerState, &SGXPostPowerState,
&SGXPreClockSpeedChange, &SGXPostClockSpeedChange,
@@ -728,17 +999,8 @@ PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
return eError;
}
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
- eError = WorkaroundBRN22997Alloc(psDeviceNode);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to alloc memory for BRN22997 workaround"));
- return eError;
- }
-#endif
-
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
+ /* map the external system cache control registers into the SGX MMU */
psDevInfo->ui32ExtSysCacheRegsSize = psSGXDeviceMap->ui32ExtSysCacheRegsSize;
psDevInfo->sExtSysCacheRegsDevPBase = psSGXDeviceMap->sExtSysCacheRegsDevPBase;
eError = MMU_MapExtSystemCacheRegs(psDeviceNode);
@@ -747,10 +1009,11 @@ PVRSRV_ERROR DevInitSGXPart2KM (PVRSRV_PER_PROCESS_DATA *psPerProc,
PVR_DPF((PVR_DBG_ERROR,"SGXInitialise : Failed to map external system cache registers"));
return eError;
}
-#endif
-
-
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
+ /*
+ Initialise the Kernel CCB
+ */
OSMemSet(psDevInfo->psKernelCCB, 0, sizeof(PVRSRV_SGX_KERNEL_CCB));
OSMemSet(psDevInfo->psKernelCCBCtl, 0, sizeof(PVRSRV_SGX_CCB_CTL));
OSMemSet(psDevInfo->pui32KernelCCBEventKicker, 0, sizeof(*psDevInfo->pui32KernelCCBEventKicker));
@@ -767,6 +1030,20 @@ failed_init_dev_info:
return eError;
}
+/*!
+*******************************************************************************
+
+ @Function DevDeInitSGX
+
+ @Description
+
+ Reset and deinitialise Chip
+
+ @Input pvDeviceNode - device info. structure
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
{
PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvDeviceNode;
@@ -778,7 +1055,7 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
if (!psDevInfo)
{
-
+ /* Can happen if DevInitSGX failed */
PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Null DevInfo"));
return PVRSRV_OK;
}
@@ -794,29 +1071,26 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
}
psDevInfo->hTimer = IMG_NULL;
}
-#endif
+#endif /* SUPPORT_HW_RECOVERY */
#if defined(SUPPORT_EXTERNAL_SYSTEM_CACHE)
-
+ /* unmap the external system cache control registers */
eError = MMU_UnmapExtSystemCacheRegs(psDeviceNode);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"DevDeInitSGX: Failed to unmap ext system cache registers"));
return eError;
}
-#endif
-
-#if defined(FIX_HW_BRN_22997) && defined(FIX_HW_BRN_23030) && defined(SGX_FEATURE_HOST_PORT)
- WorkaroundBRN22997Free(psDeviceNode);
-#endif
+#endif /* SUPPORT_EXTERNAL_SYSTEM_CACHE */
MMU_BIFResetPDFree(psDevInfo);
-
-
+ /*
+ DeinitDevInfo the DevInfo
+ */
DeinitDevInfo(psDevInfo);
-
+ /* Destroy heaps. */
psDeviceMemoryHeap = (DEVICE_MEMORY_HEAP_INFO *)psDevInfo->pvDeviceMemoryHeap;
for(ui32Heap=0; ui32Heap<psDeviceNode->sDevMemoryInfo.ui32HeapCount; ui32Heap++)
{
@@ -835,7 +1109,7 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
}
}
-
+ /* Destroy the kernel context. */
eError = BM_DestroyContext(psDeviceNode->sDevMemoryInfo.pBMKernelContext, IMG_NULL);
if (eError != PVRSRV_OK)
{
@@ -843,7 +1117,7 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
return eError;
}
-
+ /* remove the device from the power manager */
eError = PVRSRVRemovePowerDevice (((PVRSRV_DEVICE_NODE*)pvDeviceNode)->sDevId.ui32DeviceIndex);
if (eError != PVRSRV_OK)
{
@@ -858,10 +1132,10 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
return eError;
}
-
+ /* Only unmap the registers if they were mapped here */
if (!psSGXDeviceMap->pvRegsCpuVBase)
{
-
+ /* UnMap Regs */
if (psDevInfo->pvRegsBaseKM != IMG_NULL)
{
OSUnMapPhysToLin(psDevInfo->pvRegsBaseKM,
@@ -874,7 +1148,7 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
#if defined(SGX_FEATURE_HOST_PORT)
if (psSGXDeviceMap->ui32Flags & SGX_HOSTPORT_PRESENT)
{
-
+ /* unMap Host Port */
if (psDevInfo->pvHostPortBaseKM != IMG_NULL)
{
OSUnMapPhysToLin(psDevInfo->pvHostPortBaseKM,
@@ -883,10 +1157,10 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
IMG_NULL);
}
}
-#endif
+#endif /* #ifdef SGX_FEATURE_HOST_PORT */
-
+ /* DeAllocate devinfo */
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_SGXDEV_INFO),
psDevInfo,
@@ -896,7 +1170,7 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
if (psDeviceMemoryHeap != IMG_NULL)
{
-
+ /* Free the device memory heap info. */
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
psDeviceMemoryHeap,
@@ -909,6 +1183,22 @@ static PVRSRV_ERROR DevDeInitSGX (IMG_VOID *pvDeviceNode)
#if defined(RESTRICTED_REGISTERS) && defined(SGX_FEATURE_MP)
+/*!
+*******************************************************************************
+
+ @Function SGXDumpMasterDebugReg
+
+ @Description
+
+ Dump a single SGX debug register value
+
+ @Input psDevInfo - SGX device info
+ @Input pszName - string used for logging
+ @Input ui32RegAddr - SGX register offset
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXDumpMasterDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_CHAR *pszName,
IMG_UINT32 ui32RegAddr)
@@ -918,8 +1208,25 @@ static IMG_VOID SGXDumpMasterDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
PVR_LOG(("(HYD) %s%08X", pszName, ui32RegVal));
}
-#endif
+#endif /* defined(RESTRICTED_REGISTERS) */
+
+/*!
+*******************************************************************************
+
+ @Function SGXDumpDebugReg
+
+ @Description
+ Dump a single SGX debug register value
+
+ @Input psDevInfo - SGX device info
+ @Input ui32CoreNum - processor number
+ @Input pszName - string used for logging
+ @Input ui32RegAddr - SGX register offset
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32CoreNum,
IMG_CHAR *pszName,
@@ -930,8 +1237,24 @@ static IMG_VOID SGXDumpDebugReg (PVRSRV_SGXDEV_INFO *psDevInfo,
PVR_LOG(("(P%u) %s%08X", ui32CoreNum, pszName, ui32RegVal));
}
-static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
- IMG_BOOL bDumpSGXRegs)
+/*!
+*******************************************************************************
+
+ @Function SGXDumpDebugInfo
+
+ @Description
+
+ Dump useful debugging info
+
+ @Input psDevInfo - SGX device info
+ @Input bDumpSGXRegs - Whether to dump SGX debug registers. Must not be done
+ when SGX is not powered.
+
+ @Return IMG_VOID
+
+******************************************************************************/
+IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
+ IMG_BOOL bDumpSGXRegs)
{
IMG_UINT32 ui32CoreNum;
@@ -967,7 +1290,7 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
#endif
for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
{
-
+ /* Dump HW event status */
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS: ", EUR_CR_EVENT_STATUS);
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_STATUS2: ", EUR_CR_EVENT_STATUS2);
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_CTRL: ", EUR_CR_BIF_CTRL);
@@ -981,16 +1304,71 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
#if defined(EUR_CR_PDS_PC_BASE)
SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_PDS_PC_BASE: ", EUR_CR_PDS_PC_BASE);
#endif
+#if defined(RESTRICTED_REGISTERS)
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_BIF_BANK_SET: ", EUR_CR_BIF_BANK_SET);
+
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATECTL: ", EUR_CR_CLKGATECTL);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_CLKGATESTATUS: ", EUR_CR_CLKGATESTATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_MTE_CTRL: ", EUR_CR_MTE_CTRL);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_EXEC: ", EUR_CR_EVENT_OTHER_PDS_EXEC);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_DATA: ", EUR_CR_EVENT_OTHER_PDS_DATA);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_EVENT_OTHER_PDS_INFO: ", EUR_CR_EVENT_OTHER_PDS_INFO);
+
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_ZLS_PAGE_THRESHOLD: ", EUR_CR_DPM_ZLS_PAGE_THRESHOLD);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_GLOBAL_LIST: ", EUR_CR_DPM_TA_GLOBAL_LIST);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_STATE_CONTEXT_ID: ", EUR_CR_DPM_STATE_CONTEXT_ID);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_CONTEXT_PB_BASE: ", EUR_CR_DPM_CONTEXT_PB_BASE);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS1: ", EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS1);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_3D_FREE_LIST_STATUS1: ", EUR_CR_DPM_3D_FREE_LIST_STATUS1);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS2: ", EUR_CR_DPM_TA_ALLOC_FREE_LIST_STATUS2);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_3D_FREE_LIST_STATUS2: ", EUR_CR_DPM_3D_FREE_LIST_STATUS2);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_ABORT_STATUS_MTILE: ", EUR_CR_DPM_ABORT_STATUS_MTILE);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_PAGE_STATUS: ", EUR_CR_DPM_PAGE_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_PAGE: ", EUR_CR_DPM_PAGE);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_GLOBAL_PAGE_STATUS: ", EUR_CR_DPM_GLOBAL_PAGE_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_LOAD_STATUS: ", EUR_CR_VDM_CONTEXT_LOAD_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATUS: ", EUR_CR_VDM_CONTEXT_STORE_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_TASK_KICK_STATUS: ", EUR_CR_VDM_TASK_KICK_STATUS);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATE0: ", EUR_CR_VDM_CONTEXT_STORE_STATE0);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_VDM_CONTEXT_STORE_STATE1: ", EUR_CR_VDM_CONTEXT_STORE_STATE1);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_REQUESTING: ", EUR_CR_DPM_REQUESTING);
+ SGXDumpDebugReg(psDevInfo, ui32CoreNum, "EUR_CR_DPM_REQUESTING: ", EUR_CR_DPM_REQUESTING);
+
+#endif
}
}
-
+/* This code only works for _real_ single memory context chips */
+#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && !defined(FIX_HW_BRN_31620)
+ {
+ IMG_UINT32 ui32RegVal;
+ IMG_UINT32 ui32PDDevPAddr;
+
+ /*
+ If there was a SGX pagefault check the page table too see if the
+ host thinks the fault is correct
+ */
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
+ if (ui32RegVal & EUR_CR_BIF_INT_STAT_PF_N_RW_MASK)
+ {
+ ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
+ ui32RegVal &= EUR_CR_BIF_FAULT_ADDR_MASK;
+ ui32PDDevPAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0);
+ ui32PDDevPAddr &= EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK;
+ MMU_CheckFaultAddr(psDevInfo, ui32PDDevPAddr, ui32RegVal);
+ }
+ }
+#endif
+ /*
+ Dump out the outstanding queue items.
+ */
QueueDumpDebugInfo();
{
-
-
+ /*
+ Dump out the Host control.
+ */
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
IMG_UINT32 *pui32HostCtlBuffer = (IMG_UINT32 *)psSGXHostCtl;
IMG_UINT32 ui32LoopCounter;
@@ -1014,8 +1392,9 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
}
{
-
-
+ /*
+ Dump out the TA/3D control.
+ */
IMG_UINT32 *pui32TA3DCtlBuffer = psDevInfo->psKernelSGXTA3DCtlMemInfo->pvLinAddrKM;
IMG_UINT32 ui32LoopCounter;
@@ -1041,11 +1420,13 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
ui32WriteOffset = *pui32MKTraceBuffer;
pui32MKTraceBuffer++;
- PVR_LOG(("Last SGX microkernel status code: %08X", ui32LastStatusCode));
+ PVR_LOG(("Last SGX microkernel status code: %08X %s",
+ ui32LastStatusCode, SGXUKernelStatusString(ui32LastStatusCode)));
#if defined(PVRSRV_DUMP_MK_TRACE)
-
-
+ /*
+ Dump the raw microkernel trace buffer to the log.
+ */
{
IMG_UINT32 ui32LoopCounter;
@@ -1056,17 +1437,19 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 *pui32BufPtr;
pui32BufPtr = pui32MKTraceBuffer +
(((ui32WriteOffset + ui32LoopCounter) % SGXMK_TRACE_BUFFER_SIZE) * 4);
- PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X", ui32LoopCounter,
- pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0]));
+ PVR_LOG(("\t(MKT-%X) %08X %08X %08X %08X %s", ui32LoopCounter,
+ pui32BufPtr[2], pui32BufPtr[3], pui32BufPtr[1], pui32BufPtr[0],
+ SGXUKernelStatusString(pui32BufPtr[0])));
}
}
- #endif
+ #endif /* PVRSRV_DUMP_MK_TRACE */
}
- #endif
+ #endif /* PVRSRV_USSE_EDM_STATUS_DEBUG */
{
-
-
+ /*
+ Dump out the kernel CCB.
+ */
PVR_LOG(("SGX Kernel CCB WO:0x%X RO:0x%X",
psDevInfo->psKernelCCBCtl->ui32WriteOffset,
psDevInfo->psKernelCCBCtl->ui32ReadOffset));
@@ -1088,7 +1471,7 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
psCommand->ui32Data[2], psCommand->ui32Data[3]));
}
}
- #endif
+ #endif /* PVRSRV_DUMP_KERNEL_CCB */
}
#if defined (TTRACE)
PVRSRVDumpTimeTraceBuffers();
@@ -1098,6 +1481,24 @@ static IMG_VOID SGXDumpDebugInfo (PVRSRV_SGXDEV_INFO *psDevInfo,
#if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY)
+/*!
+*******************************************************************************
+
+ @Function HWRecoveryResetSGX
+
+ @Description
+
+ Resets SGX
+
+ Note: may be called from an ISR so should not call pdump.
+
+ @Input psDevInfo - dev info
+
+ @Input ui32Component - core component to reset
+
+ @Return IMG_VOID
+
+******************************************************************************/
static
IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32Component,
@@ -1106,17 +1507,25 @@ IMG_VOID HWRecoveryResetSGX (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);
-
+#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT)
+ static IMG_UINT32 ui32Clockinus = 0;
+ static IMG_UINT32 ui32HWRecoveryCount=0;
+ IMG_UINT32 ui32TempClockinus=0;
+#endif
+
+ PVR_UNREFERENCED_PARAMETER(ui32Component);
+ /*
+ Ensure that hardware recovery is serialised with any power transitions.
+ */
eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
if(eError != PVRSRV_OK)
{
-
-
-
+ /*
+ Unable to obtain lock because there is already a power transition
+ in progress.
+ */
PVR_DPF((PVR_DBG_WARNING,"HWRecoveryResetSGX: Power transition in progress"));
return;
}
@@ -1124,47 +1533,74 @@ IMG_VOID HWRecoveryResetSGX (PVRSRV_DEVICE_NODE *psDeviceNode,
psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
PVR_LOG(("HWRecoveryResetSGX: SGX Hardware Recovery triggered"));
-
+
+#if defined(SUPPORT_HWRECOVERY_TRACE_LIMIT)
+/*
+ * The following defines are system specific and should be defined in
+ * the corresponding sysconfig.h file. The values indicated are examples only.
+ SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD 5000000 //(5 Seconds)
+ SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT 5
+ */
+ ui32TempClockinus = OSClockus();
+ if((ui32TempClockinus-ui32Clockinus) < SYS_SGX_HWRECOVERY_TRACE_RESET_TIME_PERIOD){
+ ui32HWRecoveryCount++;
+ if(SYS_SGX_MAX_HWRECOVERY_OCCURANCE_COUNT <= ui32HWRecoveryCount){
+ OSPanic();
+ }
+ }else{
+ ui32Clockinus = ui32TempClockinus;
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+ ui32HWRecoveryCount = 0;
+ }
+#else
SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
-
+#endif
+ /* Suspend pdumping. */
PDUMPSUSPEND();
-
-#if defined(FIX_HW_BRN_23281)
-
- for (eError = PVRSRV_ERROR_RETRY; eError == PVRSRV_ERROR_RETRY;)
-#endif
- {
- eError = SGXInitialise(psDevInfo, IMG_TRUE);
- }
+ /* Reset and re-initialise SGX. */
+ eError = SGXInitialise(psDevInfo, IMG_TRUE);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"HWRecoveryResetSGX: SGXInitialise failed (%d)", eError));
}
-
+ /* Resume pdumping. */
PDUMPRESUME();
PVRSRVPowerUnlock(ui32CallerID);
-
+ /* Send a dummy kick so that we start processing again */
SGXScheduleProcessQueuesKM(psDeviceNode);
-
-
+ /* Flush any old commands from the queues. */
PVRSRVProcessQueues(IMG_TRUE);
}
-#endif
+#endif /* #if defined(SYS_USING_INTERRUPTS) || defined(SUPPORT_HW_RECOVERY) */
#if defined(SUPPORT_HW_RECOVERY)
+/*!
+******************************************************************************
+
+ @Function SGXOSTimer
+
+ @Description
+
+ Timer function for SGX
+
+ @Input pvData - private data
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_VOID SGXOSTimer(IMG_VOID *pvData)
{
PVRSRV_DEVICE_NODE *psDeviceNode = pvData;
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
static IMG_UINT32 ui32EDMTasks = 0;
- static IMG_UINT32 ui32LockupCounter = 0;
+ static IMG_UINT32 ui32LockupCounter = 0; /* To prevent false positives */
static IMG_UINT32 ui32OpenCLDelayCounter = 0;
static IMG_UINT32 ui32NumResets = 0;
#if defined(FIX_HW_BRN_31093)
@@ -1175,17 +1611,21 @@ IMG_VOID SGXOSTimer(IMG_VOID *pvData)
IMG_BOOL bLockup = IMG_FALSE;
IMG_BOOL bPoweredDown;
-
+ /* increment a timestamp */
psDevInfo->ui32TimeStamp++;
#if defined(NO_HARDWARE)
bPoweredDown = IMG_TRUE;
#else
bPoweredDown = (SGXIsDevicePowered(psDeviceNode)) ? IMG_FALSE : IMG_TRUE;
-#endif
+#endif /* NO_HARDWARE */
-
-
+ /*
+ * Check whether EDM timer tasks are getting scheduled. If not, assume
+ * that SGX has locked up and reset the chip.
+ */
+
+ /* Check whether the timer should be running */
if (bPoweredDown)
{
ui32LockupCounter = 0;
@@ -1195,7 +1635,7 @@ IMG_VOID SGXOSTimer(IMG_VOID *pvData)
}
else
{
-
+ /* The PDS timer should be running. */
ui32CurrentEDMTasks = OSReadHWReg(psDevInfo->pvRegsBaseKM, psDevInfo->ui32EDMTaskReg0);
if (psDevInfo->ui32EDMTaskReg1 != 0)
{
@@ -1224,31 +1664,31 @@ IMG_VOID SGXOSTimer(IMG_VOID *pvData)
#if defined(FIX_HW_BRN_31093)
if (bBRN31093Inval == IMG_FALSE)
{
-
+ /* It could be a BIF hang so do a INVAL_PTE */
#if defined(FIX_HW_BRN_29997)
IMG_UINT32 ui32BIFCtrl;
-
+ /* Pause the BIF before issuing the invalidate */
ui32BIFCtrl = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl | EUR_CR_BIF_CTRL_PAUSE_MASK);
-
+ /* delay for 200 clocks */
SGXWaitClocks(psDevInfo, 200);
#endif
-
+ /* Flag that we have attempt to un-block the BIF */
bBRN31093Inval = IMG_TRUE;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, EUR_CR_BIF_CTRL_INVAL_PTE_MASK);
-
+ /* delay for 200 clocks */
SGXWaitClocks(psDevInfo, 200);
#if defined(FIX_HW_BRN_29997)
-
+ /* un-pause the BIF by restoring the BIF_CTRL */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32BIFCtrl);
#endif
}
else
#endif
{
- 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;
(psDevInfo->psSGXHostCtl)->ui32OpenCLDelayCount = 0;
@@ -1271,24 +1711,28 @@ SGX_NoUKernel_LockUp:
{
SGXMKIF_HOST_CTL *psSGXHostCtl = (SGXMKIF_HOST_CTL *)psDevInfo->psSGXHostCtl;
-
+ /* increment the counter so we know the host detected the lockup */
psSGXHostCtl->ui32HostDetectedLockups ++;
-
+ /* Reset the chip and process the queues. */
HWRecoveryResetSGX(psDeviceNode, 0, ISR_ID);
}
}
-#endif
+#endif /* defined(SUPPORT_HW_RECOVERY) */
+
#if defined(SYS_USING_INTERRUPTS)
+/*
+ SGX ISR Handler
+*/
IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
{
IMG_BOOL bInterruptProcessed = IMG_FALSE;
-
+ /* Real Hardware */
{
IMG_UINT32 ui32EventStatus, ui32EventEnable;
IMG_UINT32 ui32EventClear = 0;
@@ -1299,7 +1743,7 @@ IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
PVRSRV_DEVICE_NODE *psDeviceNode;
PVRSRV_SGXDEV_INFO *psDevInfo;
-
+ /* check for null pointers */
if(pvData == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "SGX_ISRHandler: Invalid params\n"));
@@ -1312,18 +1756,20 @@ IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
ui32EventStatus = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
ui32EventEnable = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE);
-
+ /* test only the unmasked bits */
ui32EventStatus &= ui32EventEnable;
#if defined(SGX_FEATURE_DATA_BREAKPOINTS)
ui32EventStatus2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
ui32EventEnable2 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_ENABLE2);
-
+ /* test only the unmasked bits */
ui32EventStatus2 &= ui32EventEnable2;
-#endif
+#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */
-
+ /* Thought: is it better to insist that the bit assignment in
+ the "clear" register(s) matches that of the "status" register(s)?
+ It would greatly simplify this LISR */
if (ui32EventStatus & EUR_CR_EVENT_STATUS_SW_EVENT_MASK)
{
@@ -1340,16 +1786,16 @@ IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
{
ui32EventClear2 |= EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_TRAPPED_MASK;
}
-#endif
+#endif /* defined(SGX_FEATURE_DATA_BREAKPOINTS) */
if (ui32EventClear || ui32EventClear2)
{
bInterruptProcessed = IMG_TRUE;
-
+ /* Clear master interrupt bit */
ui32EventClear |= EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK;
-
+ /* clear the events */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32EventClear);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR2, ui32EventClear2);
}
@@ -1359,6 +1805,9 @@ IMG_BOOL SGX_ISRHandler (IMG_VOID *pvData)
}
+/*
+ SGX MISR Handler
+*/
static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
{
PVRSRV_DEVICE_NODE *psDeviceNode = (PVRSRV_DEVICE_NODE *)pvData;
@@ -1380,80 +1829,27 @@ static IMG_VOID SGX_MISRHandler (IMG_VOID *pvData)
SGXTestActivePowerEvent(psDeviceNode, ISR_ID);
}
-#endif
-
-
+#endif /* #if defined (SYS_USING_INTERRUPTS) */
#if defined(SUPPORT_MEMORY_TILING)
+
+IMG_INTERNAL
PVRSRV_ERROR SGX_AllocMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
- PVRSRV_KERNEL_MEM_INFO *psMemInfo,
- IMG_UINT32 ui32TilingStride,
- IMG_UINT32 *pui32RangeIndex)
+ PVRSRV_KERNEL_MEM_INFO *psMemInfo,
+ IMG_UINT32 ui32XTileStride,
+ IMG_UINT32 *pui32RangeIndex)
{
-#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
- PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
- IMG_UINT32 i;
- IMG_UINT32 ui32Start;
- IMG_UINT32 ui32End;
- IMG_UINT32 ui32Offset;
- IMG_UINT32 ui32Val;
-
-
- for(i=0; i<10; i++)
- {
- if((psDevInfo->ui32MemTilingUsage & (1U << i)) == 0)
- {
-
- psDevInfo->ui32MemTilingUsage |= 1U << i;
-
- *pui32RangeIndex = i;
- goto RangeAllocated;
- }
- }
-
- PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: all tiling ranges in use"));
- return PVRSRV_ERROR_EXCEEDED_HW_LIMITS;
-
-RangeAllocated:
- ui32Offset = EUR_CR_BIF_TILE0 + (i<<2);
-
- ui32Start = psMemInfo->sDevVAddr.uiAddr;
- ui32End = ui32Start + psMemInfo->uAllocSize + SGX_MMU_PAGE_SIZE - 1;
-
- ui32Val = ((ui32TilingStride << EUR_CR_BIF_TILE0_CFG_SHIFT) & EUR_CR_BIF_TILE0_CFG_MASK)
- | (((ui32End>>20) << EUR_CR_BIF_TILE0_MAX_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MAX_ADDRESS_MASK)
- | (((ui32Start>>20) << EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT) & EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK)
- | (0x8 << EUR_CR_BIF_TILE0_CFG_SHIFT);
-
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
- PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
-
- ui32Offset = EUR_CR_BIF_TILE0_ADDR_EXT + (i<<2);
-
- ui32Val = (((ui32End>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MAX_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MAX_MASK)
- | (((ui32Start>>12) << EUR_CR_BIF_TILE0_ADDR_EXT_MIN_SHIFT) & EUR_CR_BIF_TILE0_ADDR_EXT_MIN_MASK);
-
-
- OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
- PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
-
- return PVRSRV_OK;
-#else
- PVR_UNREFERENCED_PARAMETER(psDeviceNode);
- PVR_UNREFERENCED_PARAMETER(psMemInfo);
- PVR_UNREFERENCED_PARAMETER(ui32TilingStride);
- PVR_UNREFERENCED_PARAMETER(pui32RangeIndex);
-
- PVR_DPF((PVR_DBG_ERROR,"SGX_AllocMemTilingRange: device does not support memory tiling"));
- return PVRSRV_ERROR_NOT_SUPPORTED;
-#endif
+ return SGX_AllocMemTilingRangeInt(psDeviceNode->pvDevice,
+ psMemInfo->sDevVAddr.uiAddr,
+ psMemInfo->sDevVAddr.uiAddr + ((IMG_UINT32) psMemInfo->uAllocSize) + SGX_MMU_PAGE_SIZE - 1,
+ ui32XTileStride,
+ pui32RangeIndex);
}
+IMG_INTERNAL
PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32RangeIndex)
{
-#if defined(SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS)
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
IMG_UINT32 ui32Offset;
IMG_UINT32 ui32Val;
@@ -1464,27 +1860,21 @@ PVRSRV_ERROR SGX_FreeMemTilingRange(PVRSRV_DEVICE_NODE *psDeviceNode,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* clear the usage bit */
psDevInfo->ui32MemTilingUsage &= ~(1<<ui32RangeIndex);
-
+ /* disable the range */
ui32Offset = EUR_CR_BIF_TILE0 + (ui32RangeIndex<<2);
ui32Val = 0;
-
OSWriteHWReg(psDevInfo->pvRegsBaseKM, ui32Offset, ui32Val);
PDUMPREG(SGX_PDUMPREG_NAME, ui32Offset, ui32Val);
return PVRSRV_OK;
-#else
- PVR_UNREFERENCED_PARAMETER(psDeviceNode);
- PVR_UNREFERENCED_PARAMETER(ui32RangeIndex);
-
- PVR_DPF((PVR_DBG_ERROR,"SGX_FreeMemTilingRange: device does not support memory tiling"));
- return PVRSRV_ERROR_NOT_SUPPORTED;
-#endif
}
-#endif
+
+#endif /* defined(SUPPORT_MEMORY_TILING) */
+
static IMG_VOID SGXCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode)
{
@@ -1494,20 +1884,34 @@ static IMG_VOID SGXCacheInvalidate(PVRSRV_DEVICE_NODE *psDeviceNode)
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_SL;
#else
PVR_UNREFERENCED_PARAMETER(psDevInfo);
- #endif
+ #endif /* SGX_FEATURE_MP */
}
+/*!
+*******************************************************************************
+
+ @Function SGXRegisterDevice
+
+ @Description
+
+ Registers the device with the system
+
+ @Input: psDeviceNode - device node
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
{
DEVICE_MEMORY_INFO *psDevMemoryInfo;
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
-
+ /* setup details that never change */
psDeviceNode->sDevId.eDeviceType = DEV_DEVICE_TYPE;
psDeviceNode->sDevId.eDeviceClass = DEV_DEVICE_CLASS;
#if defined(PDUMP)
{
-
+ /* memory space names are set up in system code */
SGX_DEVICE_MAP *psSGXDeviceMemMap;
SysGetDeviceMemoryMap(PVRSRV_DEVICE_TYPE_SGX,
(IMG_VOID**)&psSGXDeviceMemMap);
@@ -1517,7 +1921,7 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
}
psDeviceNode->sDevId.pszPDumpRegName = SGX_PDUMPREG_NAME;
-#endif
+#endif /* PDUMP */
psDeviceNode->pfnInitDevice = &DevInitSGXPart1;
psDeviceNode->pfnDeInitDevice = &DevDeInitSGX;
@@ -1527,8 +1931,9 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceNode->pfnPDumpInitDevice = &SGXResetPDump;
psDeviceNode->pfnMMUGetContextID = &MMU_GetPDumpContextID;
#endif
-
-
+ /*
+ MMU callbacks
+ */
psDeviceNode->pfnMMUInitialise = &MMU_Initialise;
psDeviceNode->pfnMMUFinalise = &MMU_Finalise;
psDeviceNode->pfnMMUInsertHeap = &MMU_InsertHeap;
@@ -1552,9 +1957,13 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceNode->pfnMMUGetCacheFlushRange = IMG_NULL;
psDeviceNode->pfnMMUGetPDPhysAddr = IMG_NULL;
#endif
-#if defined (SYS_USING_INTERRUPTS)
-
+ psDeviceNode->pfnMMUMapPagesSparse = &MMU_MapPagesSparse;
+ psDeviceNode->pfnMMUMapShadowSparse = &MMU_MapShadowSparse;
+#if defined (SYS_USING_INTERRUPTS)
+ /*
+ SGX ISR handler
+ */
psDeviceNode->pfnDeviceISR = SGX_ISRHandler;
psDeviceNode->pfnDeviceMISR = SGX_MISRHandler;
#endif
@@ -1564,22 +1973,24 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceNode->pfnFreeMemTilingRange = SGX_FreeMemTilingRange;
#endif
-
-
+ /*
+ SGX command complete handler
+ */
psDeviceNode->pfnDeviceCommandComplete = &SGXCommandComplete;
psDeviceNode->pfnCacheInvalidate = SGXCacheInvalidate;
-
-
+ /*
+ and setup the device's memory map:
+ */
psDevMemoryInfo = &psDeviceNode->sDevMemoryInfo;
-
+ /* size of address space */
psDevMemoryInfo->ui32AddressSpaceSizeLog2 = SGX_FEATURE_ADDRESS_SPACE_SIZE;
-
+ /* flags, backing store details to be specified by system */
psDevMemoryInfo->ui32Flags = 0;
-
+ /* device memory heap info about each heap in a device address space */
if(OSAllocMem( PVRSRV_OS_PAGEABLE_HEAP,
sizeof(DEVICE_MEMORY_HEAP_INFO) * SGX_MAX_HEAP_ID,
(IMG_VOID **)&psDevMemoryInfo->psDeviceMemoryHeap, 0,
@@ -1592,10 +2003,12 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap = psDevMemoryInfo->psDeviceMemoryHeap;
-
+ /*
+ setup heaps
+ Note: backing store to be setup by system (defaults to UMA)
+ */
-
-
+ /************* general ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_HEAP_SIZE;
@@ -1605,16 +2018,50 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "General";
psDeviceMemoryHeap->pszBSName = "General BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
#if !defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
-
+ /* specify the mapping heap ID for this device */
psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
#endif
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#if defined(SUPPORT_MEMORY_TILING)
+ /************* VPB tiling ***************/
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VPB_TILED_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VPB_TILED_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_VPB_TILED_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_MEM_RAM_BACKED_ALLOCATION
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "VPB Tiled";
+ psDeviceMemoryHeap->pszBSName = "VPB Tiled BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+ /* set the default (4k). System can override these as required */
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap->ui32XTileStride = SGX_VPB_TILED_HEAP_STRIDE;
+ PVR_DPF((PVR_DBG_WARNING, "VPB tiling heap tiling stride = 0x%x", psDeviceMemoryHeap->ui32XTileStride));
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif
-
+#if defined(SUPPORT_ION)
+ /************* Ion Heap ***************/
+ psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_ION_HEAP_ID);
+ psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_ION_HEAP_BASE;
+ psDeviceMemoryHeap->ui32HeapSize = SGX_ION_HEAP_SIZE;
+ psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
+ | PVRSRV_HAP_SINGLE_PROCESS;
+ psDeviceMemoryHeap->pszName = "Ion";
+ psDeviceMemoryHeap->pszBSName = "Ion BS";
+ psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
+ /* specify the ion heap ID for this device */
+ psDevMemoryInfo->ui32IonHeapID = SGX_ION_HEAP_ID;
+ /* set the default (4k). System can override these as required */
+ psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif
+
+ /************* TA data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_TADATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_TADATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_TADATA_HEAP_SIZE;
@@ -1624,12 +2071,12 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "TA Data";
psDeviceMemoryHeap->pszBSName = "TA Data BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* kernel code ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_CODE_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_CODE_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_CODE_HEAP_SIZE;
@@ -1639,12 +2086,12 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "Kernel Code";
psDeviceMemoryHeap->pszBSName = "Kernel Code BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* Kernel Video Data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_KERNEL_DATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_KERNEL_DATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_KERNEL_DATA_HEAP_SIZE;
@@ -1654,20 +2101,21 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "KernelData";
psDeviceMemoryHeap->pszBSName = "KernelData BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* PixelShaderUSSE ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PIXELSHADER_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PIXELSHADER_HEAP_BASE;
-
-
-
-
-
-
+ /*
+ The actual size of the pixel and vertex shader heap must be such that all
+ addresses are within range of the one of the USSE code base registers, but
+ the addressable range is hardware-dependent.
+ SGX_PIXELSHADER_HEAP_SIZE is defined to be the maximum possible size
+ to ensure that the heap layout is consistent across all SGXs.
+ */
psDeviceMemoryHeap->ui32HeapSize = ((10 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_PIXELSHADER_HEAP_SIZE);
psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
@@ -1676,15 +2124,15 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "PixelShaderUSSE";
psDeviceMemoryHeap->pszBSName = "PixelShaderUSSE BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* VertexShaderUSSE ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_VERTEXSHADER_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_VERTEXSHADER_HEAP_BASE;
-
+ /* See comment above with PixelShaderUSSE ui32HeapSize */
psDeviceMemoryHeap->ui32HeapSize = ((4 << SGX_USE_CODE_SEGMENT_RANGE_BITS) - 0x00001000);
PVR_ASSERT(psDeviceMemoryHeap->ui32HeapSize <= SGX_VERTEXSHADER_HEAP_SIZE);
psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
@@ -1693,12 +2141,12 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "VertexShaderUSSE";
psDeviceMemoryHeap->pszBSName = "VertexShaderUSSE BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* PDS Pixel Code/Data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSPIXEL_CODEDATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSPIXEL_CODEDATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_PDSPIXEL_CODEDATA_HEAP_SIZE;
@@ -1708,12 +2156,12 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "PDSPixelCodeData";
psDeviceMemoryHeap->pszBSName = "PDSPixelCodeData BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* PDS Vertex Code/Data ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PDSVERTEX_CODEDATA_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PDSVERTEX_CODEDATA_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_PDSVERTEX_CODEDATA_HEAP_SIZE;
@@ -1723,12 +2171,12 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "PDSVertexCodeData";
psDeviceMemoryHeap->pszBSName = "PDSVertexCodeData BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* CacheCoherent ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SYNCINFO_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SYNCINFO_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_SYNCINFO_HEAP_SIZE;
@@ -1738,14 +2186,14 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "CacheCoherent";
psDeviceMemoryHeap->pszBSName = "CacheCoherent BS";
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
-
+ /* set the sync heap id */
psDevMemoryInfo->ui32SyncHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* Shared 3D Parameters ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_SHARED_3DPARAMETERS_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_SHARED_3DPARAMETERS_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_SHARED_3DPARAMETERS_HEAP_SIZE;
@@ -1756,11 +2204,11 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
| PVRSRV_HAP_MULTI_PROCESS;
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
-
+ /************* Percontext 3D Parameters ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_PERCONTEXT_3DPARAMETERS_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_PERCONTEXT_3DPARAMETERS_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_PERCONTEXT_3DPARAMETERS_HEAP_SIZE;
@@ -1770,13 +2218,13 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
| PVRSRV_MEM_RAM_BACKED_ALLOCATION
| PVRSRV_HAP_SINGLE_PROCESS;
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
+ psDeviceMemoryHeap++;/* advance to the next heap */
#if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP)
-
+ /************* General Mapping ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_MAPPING_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_GENERAL_MAPPING_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_GENERAL_MAPPING_HEAP_SIZE;
@@ -1786,28 +2234,29 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
psDeviceMemoryHeap->pszName = "GeneralMapping";
psDeviceMemoryHeap->pszBSName = "GeneralMapping BS";
#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410)
-
-
-
-
-
-
-
+ /*
+ if((2D hardware is enabled)
+ && (multi-mem contexts enabled)
+ && (BRN23410 is present))
+ - then don't make the heap per-context otherwise
+ the TA and 2D requestors must always be aligned to
+ the same address space which could affect performance
+ */
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
- #else
+ #else /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
- #endif
+ #endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) && defined(FIX_HW_BRN_23410) */
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
-
+ /* specify the mapping heap ID for this device */
psDevMemoryInfo->ui32MappingHeapID = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
- psDeviceMemoryHeap++;
-#endif
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif /* #if defined(SUPPORT_SGX_GENERAL_MAPPING_HEAP) */
#if defined(SGX_FEATURE_2D_HARDWARE)
-
+ /************* 2D HW Heap ***************/
psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_2D_HEAP_ID);
psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_2D_HEAP_BASE;
psDeviceMemoryHeap->ui32HeapSize = SGX_2D_HEAP_SIZE;
@@ -1816,33 +2265,14 @@ PVRSRV_ERROR SGXRegisterDevice (PVRSRV_DEVICE_NODE *psDeviceNode)
| PVRSRV_HAP_SINGLE_PROCESS;
psDeviceMemoryHeap->pszName = "2D";
psDeviceMemoryHeap->pszBSName = "2D BS";
-
psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_SHARED_EXPORTED;
-
+ /* set the default (4k). System can override these as required */
psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
-#endif
-
+ psDeviceMemoryHeap++;/* advance to the next heap */
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE) */
-#if defined(FIX_HW_BRN_26915)
-
-
- psDeviceMemoryHeap->ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_CGBUFFER_HEAP_ID);
- psDeviceMemoryHeap->sDevVAddrBase.uiAddr = SGX_CGBUFFER_HEAP_BASE;
- psDeviceMemoryHeap->ui32HeapSize = SGX_CGBUFFER_HEAP_SIZE;
- psDeviceMemoryHeap->ui32Attribs = PVRSRV_HAP_WRITECOMBINE
- | PVRSRV_MEM_RAM_BACKED_ALLOCATION
- | PVRSRV_HAP_SINGLE_PROCESS;
- psDeviceMemoryHeap->pszName = "CGBuffer";
- psDeviceMemoryHeap->pszBSName = "CGBuffer BS";
- psDeviceMemoryHeap->DevMemHeapType = DEVICE_MEMORY_HEAP_PERCONTEXT;
-
- psDeviceMemoryHeap->ui32DataPageSize = SGX_MMU_PAGE_SIZE;
- psDeviceMemoryHeap++;
-#endif
-
-
+ /* set the heap count */
psDevMemoryInfo->ui32HeapCount = (IMG_UINT32)(psDeviceMemoryHeap - psDevMemoryInfo->psDeviceMemoryHeap);
return PVRSRV_OK;
@@ -1858,32 +2288,64 @@ PVRSRV_ERROR SGXResetPDump(PVRSRV_DEVICE_NODE *psDeviceNode)
return PVRSRV_OK;
}
-#endif
+#endif /* PDUMP */
+
+
+/*!
+*******************************************************************************
+
+ @Function SGXGetClientInfoKM
+
+ @Description Gets the client information
+ @Input hDevCookie
+ @Output psClientInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGXGetClientInfoKM(IMG_HANDLE hDevCookie,
SGX_CLIENT_INFO* psClientInfo)
{
PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
-
-
+ /*
+ If this is the first client to connect to SGX perform initialisation
+ */
psDevInfo->ui32ClientRefCount++;
-
-
+ /*
+ Copy information to the client info.
+ */
psClientInfo->ui32ProcessID = OSGetCurrentProcessIDKM();
-
-
+ /*
+ Copy requested information.
+ */
OSMemCopy(&psClientInfo->asDevData, &psDevInfo->asSGXDevData, sizeof(psClientInfo->asDevData));
-
+ /* just return OK */
return PVRSRV_OK;
}
+/*!
+*******************************************************************************
+
+ @Function SGXPanic
+
+ @Description
+
+ Called when an unrecoverable situation is detected. Dumps SGX debug
+ information and tells the OS to panic.
+
+ @Input psDevInfo - SGX device info
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo)
{
PVR_LOG(("SGX panic"));
@@ -1892,6 +2354,21 @@ IMG_VOID SGXPanic(PVRSRV_SGXDEV_INFO *psDevInfo)
}
+/*!
+*******************************************************************************
+
+ @Function SGXDevInitCompatCheck
+
+ @Description
+
+ Check compatibility of host driver and microkernel (DDK and build options)
+ for SGX devices at services/device initialisation
+
+ @Input psDeviceNode - device node
+
+ @Return PVRSRV_ERROR - depending on mismatch found
+
+******************************************************************************/
PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
@@ -1899,12 +2376,12 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
IMG_UINT32 ui32BuildOptions, ui32BuildOptionsMismatch;
#if !defined(NO_HARDWARE)
PPVRSRV_KERNEL_MEM_INFO psMemInfo;
- PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; /*!< internal misc info for ukernel */
PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
- SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; /*!< microkernel structure sizes */
IMG_BOOL bStructSizesFailed;
-
+ /* Exceptions list for core rev check, format is pairs of (hw rev, sw rev) */
IMG_BOOL bCheckCoreRev;
const IMG_UINT32 aui32CoreRevExceptions[] =
{
@@ -1914,7 +2391,7 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
IMG_UINT i;
#endif
-
+ /* Ensure it's a SGX device */
if(psDeviceNode->sDevId.eDeviceType != PVRSRV_DEVICE_TYPE_SGX)
{
PVR_LOG(("(FAIL) SGXInit: Device not of type SGX"));
@@ -1924,8 +2401,16 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
psDevInfo = psDeviceNode->pvDevice;
-
-
+ /*
+ * 1. Check kernel-side and client-side build options
+ * 2. Ensure ukernel DDK version and driver DDK version are compatible
+ * 3. Check ukernel build options against kernel-side build options
+ */
+
+ /*
+ * Check KM build options against client-side host driver
+ */
+
ui32BuildOptions = (SGX_BUILD_OPTIONS);
if (ui32BuildOptions != psDevInfo->ui32ClientBuildOptions)
{
@@ -1954,13 +2439,15 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
#if !defined (NO_HARDWARE)
psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
-
+ /* Clear state (not strictly necessary since this is the first call) */
psSGXMiscInfoInt = psMemInfo->pvLinAddrKM;
psSGXMiscInfoInt->ui32MiscInfoFlags = 0;
psSGXMiscInfoInt->ui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_GET_STRUCT_SIZES;
eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, IMG_NULL);
-
+ /*
+ * Validate DDK version
+ */
if(eError != PVRSRV_OK)
{
PVR_LOG(("(FAIL) SGXInit: Unable to validate device DDK version"));
@@ -1976,7 +2463,6 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
PVR_LOG(("(FAIL) SGXInit: Incompatible driver DDK revision (%d)/device DDK revision (%d).",
PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
eError = PVRSRV_ERROR_DDK_VERSION_MISMATCH;
- PVR_DBG_BREAK;
goto chk_exit;
}
else
@@ -1985,17 +2471,22 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
PVRVERSION_BUILD, psSGXFeatures->ui32DDKBuild));
}
-
+ /*
+ * Check hardware core revision is compatible with the one in software
+ */
if (psSGXFeatures->ui32CoreRevSW == 0)
{
-
-
+ /*
+ Head core revision cannot be checked.
+ */
PVR_LOG(("SGXInit: HW core rev (%x) check skipped.",
psSGXFeatures->ui32CoreRev));
}
else
{
-
+ /* For some cores the hw/sw core revisions are expected not to match. For these
+ * exceptional cases the core rev compatibility check should be skipped.
+ */
bCheckCoreRev = IMG_TRUE;
for(i=0; i<ui32NumCoreExceptions; i+=2)
{
@@ -2026,7 +2517,9 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
}
}
-
+ /*
+ * Check ukernel structure sizes are the same as those in the driver
+ */
psSGXStructSizes = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXStructSizes;
bStructSizesFailed = IMG_FALSE;
@@ -2061,7 +2554,10 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: SGXMKIF structure sizes match. [ OK ]"));
}
-
+ /*
+ * Check ukernel build options against KM host driver
+ */
+
ui32BuildOptions = psSGXFeatures->ui32BuildOptions;
if (ui32BuildOptions != (SGX_BUILD_OPTIONS))
{
@@ -2086,7 +2582,7 @@ PVRSRV_ERROR SGXDevInitCompatCheck(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVR_DPF((PVR_DBG_MESSAGE, "SGXInit: Driver and microkernel build options match. [ OK ]"));
}
-#endif
+#endif // NO_HARDWARE
eError = PVRSRV_OK;
chk_exit:
@@ -2097,16 +2593,27 @@ chk_exit:
#endif
}
+/*
+ * @Function SGXGetMiscInfoUkernel
+ *
+ * @Description Returns misc info (e.g. SGX build info/flags) from microkernel
+ *
+ * @Input psDevInfo : device info from init phase
+ * @Input psDeviceNode : device node, used for scheduling ukernel to query SGX features
+ *
+ * @Return PVRSRV_ERROR :
+ *
+ */
static
PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_HANDLE hDevMemContext)
{
PVRSRV_ERROR eError;
- SGXMKIF_COMMAND sCommandData;
- PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt;
- PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
- SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes;
+ SGXMKIF_COMMAND sCommandData; /* CCB command data */
+ PVRSRV_SGX_MISCINFO_INFO *psSGXMiscInfoInt; /*!< internal misc info for ukernel */
+ PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures; /*!< sgx features for client */
+ SGX_MISCINFO_STRUCT_SIZES *psSGXStructSizes; /*!< internal info: microkernel structure sizes */
PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
@@ -2121,12 +2628,12 @@ PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
psSGXMiscInfoInt->ui32MiscInfoFlags &= ~PVRSRV_USSE_MISCINFO_READY;
-
+ /* Reset SGX features */
OSMemSet(psSGXFeatures, 0, sizeof(*psSGXFeatures));
OSMemSet(psSGXStructSizes, 0, sizeof(*psSGXStructSizes));
-
- sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr;
+ /* set up buffer address for SGX features in CCB */
+ sCommandData.ui32Data[1] = psMemInfo->sDevVAddr.uiAddr; /* device V addr of output buffer */
PDUMPCOMMENT("Microkernel kick for SGXGetMiscInfo");
eError = SGXScheduleCCBCommandKM(psDeviceNode,
@@ -2143,7 +2650,9 @@ PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
return eError;
}
-
+ /* FIXME: DWORD value to determine code path in ukernel?
+ * E.g. could use getMiscInfo to obtain register values for diagnostics? */
+
#if !defined(NO_HARDWARE)
{
IMG_BOOL bExit;
@@ -2158,20 +2667,33 @@ PVRSRV_ERROR SGXGetMiscInfoUkernel(PVRSRV_SGXDEV_INFO *psDevInfo,
}
} END_LOOP_UNTIL_TIMEOUT();
-
+ /*if the loop exited because a timeout*/
if (!bExit)
{
PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoUkernel: Timeout occurred waiting for misc info."));
return PVRSRV_ERROR_TIMEOUT;
}
}
-#endif
+#endif /* NO_HARDWARE */
return PVRSRV_OK;
}
+/*
+ * @Function SGXGetMiscInfoKM
+ *
+ * @Description Returns miscellaneous SGX info
+ *
+ * @Input psDevInfo : device info from init phase
+ * @Input psDeviceNode : device node, used for scheduling ukernel to query SGX features
+ *
+ * @Output psMiscInfo : query request plus user-mode mem for holding returned data
+ *
+ * @Return PVRSRV_ERROR :
+ *
+ */
IMG_EXPORT
PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
SGX_MISC_INFO *psMiscInfo,
@@ -2182,7 +2704,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
IMG_UINT32 *pui32MiscInfoFlags = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->ui32MiscInfoFlags;
-
+ /* Reset the misc info state flags */
*pui32MiscInfoFlags = 0;
#if !defined(SUPPORT_SGX_EDM_MEMORY_DEBUG)
@@ -2203,14 +2725,14 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32EndRegVal;
SGXMKIF_COMMAND sCommandData;
-
+ /* Set or Clear BP? */
if(psMiscInfo->uData.sSGXBreakpointInfo.bBPEnable)
{
-
+ /* set the break point */
IMG_DEV_VIRTADDR sBPDevVAddr = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddr;
IMG_DEV_VIRTADDR sBPDevVAddrEnd = psMiscInfo->uData.sSGXBreakpointInfo.sBPDevVAddrEnd;
-
+ /* BP address */
ui32StartRegVal = sBPDevVAddr.uiAddr & EUR_CR_BREAKPOINT0_START_ADDRESS_MASK;
ui32EndRegVal = sBPDevVAddrEnd.uiAddr & EUR_CR_BREAKPOINT0_END_ADDRESS_MASK;
@@ -2219,7 +2741,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32CtrlREnable = psMiscInfo->uData.sSGXBreakpointInfo.bRead;
ui32CtrlTrapEnable = psMiscInfo->uData.sSGXBreakpointInfo.bTrapped;
-
+ /* normal data BP */
ui32RegVal = ((ui32MaskDM<<EUR_CR_BREAKPOINT0_MASK_DM_SHIFT) & EUR_CR_BREAKPOINT0_MASK_DM_MASK) |
((ui32CtrlWEnable<<EUR_CR_BREAKPOINT0_CTRL_WENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_WENABLE_MASK) |
((ui32CtrlREnable<<EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT) & EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK) |
@@ -2227,17 +2749,17 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
}
else
{
-
+ /* clear the break point */
ui32RegVal = ui32StartRegVal = ui32EndRegVal = 0;
}
-
+ /* setup the command */
sCommandData.ui32Data[0] = psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex;
sCommandData.ui32Data[1] = ui32StartRegVal;
sCommandData.ui32Data[2] = ui32EndRegVal;
sCommandData.ui32Data[3] = ui32RegVal;
-
+ /* clear signal flags */
psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
PDUMPCOMMENT("Microkernel kick for setting a data breakpoint");
@@ -2256,7 +2778,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
}
#if defined(NO_HARDWARE)
-
+ /* clear signal flags */
psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
#else
{
@@ -2268,43 +2790,46 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
if (psDevInfo->psSGXHostCtl->ui32BPSetClearSignal != 0)
{
bExit = IMG_TRUE;
-
+ /* clear signal flags */
psDevInfo->psSGXHostCtl->ui32BPSetClearSignal = 0;
break;
}
} END_LOOP_UNTIL_TIMEOUT();
-
+ /*if the loop exited because a timeout*/
if (!bExit)
{
PVR_DPF((PVR_DBG_ERROR, "SGXGetMiscInfoKM: Timeout occurred waiting BP set/clear"));
return PVRSRV_ERROR_TIMEOUT;
}
}
-#endif
+#endif /* NO_HARDWARE */
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_POLL_BREAKPOINT:
{
-
-
-
-
-
-
-
+ /* This request checks to see whether a breakpoint has
+ been trapped. If so, it returns the number of the
+ breakpoint number that was trapped in ui32BPIndex,
+ sTrappedBPDevVAddr to the address which was trapped,
+ and sets bTrappedBP. Otherwise, bTrappedBP will be
+ false, and other fields should be ignored. */
+ /* The uKernel is not used, since if we are stopped on a
+ breakpoint, it is not possible to guarantee that the
+ uKernel would be able to run */
#if !defined(NO_HARDWARE)
#if defined(SGX_FEATURE_MP)
IMG_BOOL bTrappedBPMaster;
IMG_UINT32 ui32CoreNum, ui32TrappedBPCoreNum;
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
IMG_UINT32 ui32PipeNum, ui32TrappedBPPipeNum;
+/* ui32PipeNum is the pipe number plus 1, or 0 to represent "partition" */
#define NUM_PIPES_PLUS_ONE (SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES+1)
#endif
IMG_BOOL bTrappedBPAny;
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
IMG_BOOL bFoundOne;
#if defined(SGX_FEATURE_MP)
@@ -2312,14 +2837,15 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
bTrappedBPMaster = !!(EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT));
bTrappedBPAny = bTrappedBPMaster;
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
- ui32TrappedBPPipeNum = 0;
+ ui32TrappedBPPipeNum = 0; /* just to keep the (incorrect) compiler happy */
#endif
for (ui32CoreNum = 0; ui32CoreNum < SGX_FEATURE_MP_CORE_COUNT_3D; ui32CoreNum++)
{
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
-
-
-
+ /* FIXME: this macro makes the assumption that the PARTITION regs are the same
+ distance before the PIPE0 regs as the PIPE1 regs are after it, _and_
+ assumes that the fields in the partition regs are in the same place
+ in the pipe regs. Need to validate these assumptions, or assert them */
#define SGX_MP_CORE_PIPE_SELECT(r,c,p) \
((SGX_MP_CORE_SELECT(EUR_CR_PARTITION_##r,c) + p*(EUR_CR_PIPE0_##r-EUR_CR_PARTITION_##r)))
for (ui32PipeNum = 0; ui32PipeNum < NUM_PIPES_PLUS_ONE; ui32PipeNum++)
@@ -2337,23 +2863,23 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32TrappedBPPipeNum = ui32PipeNum;
}
}
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
bFoundOne = !!(EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum)));
if (bFoundOne)
{
bTrappedBPAny = IMG_TRUE;
ui32TrappedBPCoreNum = ui32CoreNum;
}
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
}
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = bTrappedBPAny;
-#else
+#else /* defined(SGX_FEATURE_MP) */
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
#error Not yet considered the case for per-pipe regs in non-mp case
#endif
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP = 0 != (EUR_CR_BREAKPOINT_TRAPPED_MASK & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT));
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
if (psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBP)
{
@@ -2363,14 +2889,14 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum, ui32TrappedBPPipeNum));
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO0, ui32TrappedBPCoreNum));
ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, bTrappedBPMaster?EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1:SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP_INFO1, ui32TrappedBPCoreNum));
-#endif
-#else
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#else /* defined(SGX_FEATURE_MP) */
ui32Info0 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO0);
ui32Info1 = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BREAKPOINT_TRAP_INFO1);
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
#ifdef SGX_FEATURE_PERPIPE_BKPT_REGS
psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
@@ -2379,41 +2905,41 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK);
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
psMiscInfo->uData.sSGXBreakpointInfo.ui32BPIndex = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_NUMBER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.sTrappedBPDevVAddr.uiAddr = ui32Info0 & EUR_CR_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK;
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPBurstLength = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.bTrappedBPRead = !!(ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_RNW_MASK);
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPDataMaster = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_DATA_MASTER_SHIFT;
psMiscInfo->uData.sSGXBreakpointInfo.ui32TrappedBPTag = (ui32Info1 & EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_MASK) >> EUR_CR_BREAKPOINT_TRAP_INFO1_TAG_SHIFT;
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
#if defined(SGX_FEATURE_MP)
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
-
+ /* mp, per-pipe regbanks */
psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:(ui32TrappedBPCoreNum + (ui32TrappedBPPipeNum<<10));
-#else
-
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+ /* mp, regbanks unsplit */
psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = bTrappedBPMaster?65535:ui32TrappedBPCoreNum;
-#endif
-#else
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#else /* defined(SGX_FEATURE_MP) */
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
-
+ /* non-mp, per-pipe regbanks */
#error non-mp perpipe regs not yet supported
-#else
-
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+ /* non-mp */
psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum = 65534;
-#endif
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
+#endif /* defined(SGX_FEATURE_MP) */
}
-#endif
+#endif /* !defined(NO_HARDWARE) */
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_RESUME_BREAKPOINT:
{
-
-
-
+ /* This request resumes from the currently trapped breakpoint. */
+ /* Core number must be supplied */
+ /* Polls for notify to be acknowledged by h/w */
#if !defined(NO_HARDWARE)
#if defined(SGX_FEATURE_MP)
IMG_UINT32 ui32CoreNum;
@@ -2421,7 +2947,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
IMG_UINT32 ui32PipeNum;
#endif
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
IMG_UINT32 ui32OldSeqNum, ui32NewSeqNum;
#if defined(SGX_FEATURE_MP)
@@ -2429,14 +2955,14 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32PipeNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum >> 10;
ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum & 1023;
bMaster = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum > 32767;
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
ui32CoreNum = psMiscInfo->uData.sSGXBreakpointInfo.ui32CoreNum;
bMaster = ui32CoreNum > SGX_FEATURE_MP_CORE_COUNT_3D;
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
if (bMaster)
{
-
-
+ /* master */
+ /* EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK | EUR_CR_MASTER_BREAKPOINT_SEQNUM_MASK */
ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BREAKPOINT_TRAP, EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK);
do
@@ -2446,9 +2972,9 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
while (ui32OldSeqNum == ui32NewSeqNum);
}
else
-#endif
+#endif /* defined(SGX_FEATURE_MP) */
{
-
+ /* core */
#if defined(SGX_FEATURE_PERPIPE_BKPT_REGS)
ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT_TRAP, ui32CoreNum, ui32PipeNum), EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK);
@@ -2457,7 +2983,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_PIPE_SELECT(BREAKPOINT, ui32CoreNum, ui32PipeNum));
}
while (ui32OldSeqNum == ui32NewSeqNum);
-#else
+#else /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
ui32OldSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
OSWriteHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT_TRAP, ui32CoreNum), EUR_CR_BREAKPOINT_TRAP_WRNOTIFY_MASK | EUR_CR_BREAKPOINT_TRAP_CONTINUE_MASK);
do
@@ -2465,12 +2991,12 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32NewSeqNum = 0x1c & OSReadHWReg(psDevInfo->pvRegsBaseKM, SGX_MP_CORE_SELECT(EUR_CR_BREAKPOINT, ui32CoreNum));
}
while (ui32OldSeqNum == ui32NewSeqNum);
-#endif
+#endif /* defined(SGX_FEATURE_PERPIPE_BKPT_REGS) */
}
-#endif
+#endif /* !defined(NO_HARDWARE) */
return PVRSRV_OK;
}
-#endif
+#endif /* SGX_FEATURE_DATA_BREAKPOINTS) */
case SGX_MISC_INFO_REQUEST_CLOCKSPEED:
{
@@ -2498,13 +3024,15 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
case SGX_MISC_INFO_REQUEST_SPM:
{
-
+ /* this is dealt with in UM */
return PVRSRV_OK;
}
case SGX_MISC_INFO_REQUEST_SGXREV:
{
PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
+// PPVRSRV_KERNEL_MEM_INFO psMemInfo = psDevInfo->psKernelSGXMiscMemInfo;
+
eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode, hDevMemContext);
if(eError != PVRSRV_OK)
{
@@ -2514,10 +3042,10 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
}
psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
-
+ /* Copy SGX features into misc info struct, to return to client */
psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
-
+ /* Debug output */
PVR_DPF((PVR_DBG_MESSAGE, "SGXGetMiscInfoKM: Core 0x%x, sw ID 0x%x, sw Rev 0x%x\n",
psSGXFeatures->ui32CoreRev,
psSGXFeatures->ui32CoreIdSW,
@@ -2526,7 +3054,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
psSGXFeatures->ui32DDKVersion,
psSGXFeatures->ui32DDKBuild));
-
+ /* done! */
return PVRSRV_OK;
}
@@ -2536,7 +3064,9 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
psSGXFeatures = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXFeatures;
-
+ /* Reset the misc information to prevent
+ * confusion with values returned from the ukernel
+ */
OSMemSet(psMemInfo->pvLinAddrKM, 0,
sizeof(PVRSRV_SGX_MISCINFO_INFO));
@@ -2546,16 +3076,16 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRVERSION_BRANCH;
psSGXFeatures->ui32DDKBuild = PVRVERSION_BUILD;
-
+ /* Also report the kernel module build options -- used in SGXConnectionCheck() */
psSGXFeatures->ui32BuildOptions = (SGX_BUILD_OPTIONS);
#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG)
-
+ /* Report the EDM status buffer location in memory */
psSGXFeatures->sDevVAEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->sDevVAddr;
psSGXFeatures->pvEDMStatusBuffer = psDevInfo->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
#endif
-
+ /* Copy SGX features into misc info struct, to return to client */
psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
return PVRSRV_OK;
}
@@ -2566,17 +3096,17 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
{
PVRSRV_ERROR eError;
PVRSRV_SGX_MISCINFO_FEATURES *psSGXFeatures;
- PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc;
- PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest;
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemSrc; /* user-defined mem read */
+ PVRSRV_SGX_MISCINFO_MEMACCESS *psSGXMemDest; /* user-defined mem write */
{
-
+ /* Set the mem read flag; src is user-defined */
*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMREAD;
psSGXMemSrc = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessSrc;
if(psMiscInfo->sDevVAddrSrc.uiAddr != 0)
{
- psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc;
+ psSGXMemSrc->sDevVAddr = psMiscInfo->sDevVAddrSrc; /* src address */
}
else
{
@@ -2586,13 +3116,13 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
if( psMiscInfo->eRequest == SGX_MISC_INFO_REQUEST_MEMCOPY)
{
-
+ /* Set the mem write flag; dest is user-defined */
*pui32MiscInfoFlags |= PVRSRV_USSE_MISCINFO_MEMWRITE;
psSGXMemDest = &((PVRSRV_SGX_MISCINFO_INFO*)(psMemInfo->pvLinAddrKM))->sSGXMemAccessDest;
if(psMiscInfo->sDevVAddrDest.uiAddr != 0)
{
- psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest;
+ psSGXMemDest->sDevVAddr = psMiscInfo->sDevVAddrDest; /* dest address */
}
else
{
@@ -2600,12 +3130,12 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
}
}
-
+ /* Get physical address of PD for memory read (may need to switch context in microkernel) */
if(psMiscInfo->hDevMemContext != IMG_NULL)
{
SGXGetMMUPDAddrKM( (IMG_HANDLE)psDeviceNode, hDevMemContext, &psSGXMemSrc->sPDDevPAddr);
-
+ /* Single app will always use the same src and dest mem context */
psSGXMemDest->sPDDevPAddr = psSGXMemSrc->sPDDevPAddr;
}
else
@@ -2613,7 +3143,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
+ /* Submit the task to the ukernel */
eError = SGXGetMiscInfoUkernel(psDevInfo, psDeviceNode);
if(eError != PVRSRV_OK)
{
@@ -2629,11 +3159,11 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
return PVRSRV_ERROR_INVALID_MISCINFO;
}
#endif
-
+ /* Copy SGX features into misc info struct, to return to client */
psMiscInfo->uData.sSGXFeatures = *psSGXFeatures;
return PVRSRV_OK;
}
-#endif
+#endif /* SUPPORT_SGX_EDM_MEMORY_DEBUG */
#if defined(SUPPORT_SGX_HWPERF)
case SGX_MISC_INFO_REQUEST_SET_HWPERF_STATUS:
@@ -2645,7 +3175,7 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_SGX_HWPERF_STATUS_MK_EXECUTION_ON;
SGXMKIF_COMMAND sCommandData = {0};
-
+ /* Check for valid flags */
if ((psSetHWPerfStatus->ui32NewHWPerfStatus & ~ui32ValidFlags) != 0)
{
return PVRSRV_ERROR_INVALID_PARAMS;
@@ -2655,9 +3185,9 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS,
"SGX ukernel HWPerf status %u\n",
psSetHWPerfStatus->ui32NewHWPerfStatus);
- #endif
+ #endif /* PDUMP */
-
+ /* Copy the new group selector(s) to the host ctl for the ukernel */
#if defined(SGX_FEATURE_EXTENDED_PERF_COUNTERS)
OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfGroup[0],
&psSetHWPerfStatus->aui32PerfGroup[0],
@@ -2665,6 +3195,8 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
OSMemCopy(&psDevInfo->psSGXHostCtl->aui32PerfBit[0],
&psSetHWPerfStatus->aui32PerfBit[0],
sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit));
+ psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect = psSetHWPerfStatus->ui32PerfCounterBitSelect;
+ psDevInfo->psSGXHostCtl->ui32PerfSumMux = psSetHWPerfStatus->ui32PerfSumMux;
#if defined(PDUMP)
PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
offsetof(SGXMKIF_HOST_CTL, aui32PerfGroup),
@@ -2676,7 +3208,17 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
sizeof(psDevInfo->psSGXHostCtl->aui32PerfBit),
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PerfCounterBitSelect),
+ sizeof(psDevInfo->psSGXHostCtl->ui32PerfCounterBitSelect),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ PDUMPMEM(IMG_NULL, psDevInfo->psKernelSGXHostCtlMemInfo,
+ offsetof(SGXMKIF_HOST_CTL, ui32PerfSumMux),
+ sizeof(psDevInfo->psSGXHostCtl->ui32PerfSumMux),
+ PDUMP_FLAGS_CONTINUOUS,
+ MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
+ #endif /* PDUMP */
#else
psDevInfo->psSGXHostCtl->ui32PerfGroup = psSetHWPerfStatus->ui32PerfGroup;
#if defined(PDUMP)
@@ -2685,10 +3227,10 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
sizeof(psDevInfo->psSGXHostCtl->ui32PerfGroup),
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
- #endif
+ #endif /* PDUMP */
+ #endif /* SGX_FEATURE_EXTENDED_PERF_COUNTERS */
-
+ /* Kick the ukernel to update the hardware state */
sCommandData.ui32Data[0] = psSetHWPerfStatus->ui32NewHWPerfStatus;
eError = SGXScheduleCCBCommandKM(psDeviceNode,
SGXMKIF_CMD_SETHWPERFSTATUS,
@@ -2699,18 +3241,30 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_FALSE);
return eError;
}
-#endif
+#endif /* SUPPORT_SGX_HWPERF */
case SGX_MISC_INFO_DUMP_DEBUG_INFO:
{
PVR_LOG(("User requested SGX debug info"));
-
+ /* Dump SGX debug data to the kernel log. */
SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_FALSE);
return PVRSRV_OK;
}
+ case SGX_MISC_INFO_DUMP_DEBUG_INFO_FORCE_REGS:
+ {
+ PVR_LOG(("User requested SGX debug info"));
+
+ /* Dump SGX debug data to the kernel log. */
+ SGXDumpDebugInfo(psDeviceNode->pvDevice, IMG_TRUE);
+
+ return PVRSRV_OK;
+ }
+
+#if defined(DEBUG)
+ /* Don't allow user-mode to reboot the device in production drivers */
case SGX_MISC_INFO_PANIC:
{
PVR_LOG(("User requested SGX panic"));
@@ -2719,10 +3273,11 @@ PVRSRV_ERROR SGXGetMiscInfoKM(PVRSRV_SGXDEV_INFO *psDevInfo,
return PVRSRV_OK;
}
+#endif
default:
{
-
+ /* switch statement fell though, so: */
return PVRSRV_ERROR_INVALID_PARAMS;
}
}
@@ -2777,3 +3332,6 @@ PVRSRV_ERROR SGXReadHWPerfCBKM(IMG_HANDLE hDevHandle,
}
+/******************************************************************************
+ End of file (sgxinit.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxkick.c b/sgx/services4/srvkm/devices/sgx/sgxkick.c
index d1220cf..5d74251 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxkick.c
+++ b/sgx/services4/srvkm/devices/sgx/sgxkick.c
@@ -1,30 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
-#include <stddef.h>
+/*************************************************************************/ /*!
+@Title Device specific kickTA routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+#include <stddef.h> /* For the macro offsetof() */
#include "services_headers.h"
#include "sgxinfo.h"
#include "sgxinfokm.h"
@@ -38,6 +54,20 @@
#include "sgxutils.h"
#include "ttrace.h"
+/*!
+******************************************************************************
+
+ @Function SGXDoKickKM
+
+ @Description
+
+ Really kicks the TA
+
+ @Input hDevHandle - Device handle
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
IMG_EXPORT
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK_KM *psCCBKick)
@@ -62,15 +92,15 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT, KICK_TOKEN_DOKICK);
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
+ /* override QAC warning about stricter alignment */
+ /* PRQA S 3305 1 */
psTACmd = CCB_DATA_FROM_OFFSET(SGXMKIF_CMDTA_SHARED, psCCBMemInfo, psCCBKick, ui32CCBOffset);
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_START, KICK_TOKEN_DOKICK);
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CCB,
KICK_TOKEN_CCB_OFFSET, psCCBKick->ui32CCBOffset);
-
+ /* TA/3D dependency */
if (psCCBKick->hTA3DSyncInfo)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
@@ -119,7 +149,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psTACmd->ui32NumTAStatusVals = psCCBKick->ui32NumTAStatusVals;
if (psCCBKick->ui32NumTAStatusVals != 0)
{
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
@@ -135,7 +165,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psTACmd->ui32Num3DStatusVals = psCCBKick->ui32Num3DStatusVals;
if (psCCBKick->ui32Num3DStatusVals != 0)
{
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
@@ -150,7 +180,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST sync dependencies */
psTACmd->ui32NumTASrcSyncs = psCCBKick->ui32NumTASrcSyncs;
for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
{
@@ -159,9 +189,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psTACmd->asTASrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->asTASrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
psTACmd->asTASrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB. */
psTACmd->asTASrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
}
@@ -173,9 +203,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psTACmd->asTADstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->asTADstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB */
psTACmd->asTADstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB - before incrementing */
psTACmd->asTADstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
}
@@ -187,13 +217,13 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psTACmd->as3DSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->as3DSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
psTACmd->as3DSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB. */
psTACmd->as3DSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
}
-#else
-
+#else /* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
+ /* texture dependencies */
psTACmd->ui32NumSrcSyncs = psCCBKick->ui32NumSrcSyncs;
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
@@ -205,12 +235,12 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psTACmd->asSrcSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psTACmd->asSrcSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
-
+ /* Get ui32ReadOpsPending snapshot and copy into the CCB - before incrementing. */
psTACmd->asSrcSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending++;
-
+ /* Copy ui32WriteOpsPending snapshot into the CCB. */
psTACmd->asSrcSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
if (psCCBKick->bFirstKickOrResume && psCCBKick->ui32NumDstSyncObjects > 0)
{
@@ -242,15 +272,18 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
if (psSyncInfo)
{
+ psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_KICK, KICK_TOKEN_DST_SYNC,
psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending++;
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
#if defined(PDUMP)
if (PDumpIsCaptureFrameKM())
@@ -262,6 +295,8 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal);
IMG_UINT32 ui32ROpsOffset = ui32SyncOffset
+ offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal);
+ IMG_UINT32 ui32ROps2Offset = ui32SyncOffset
+ + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal);
PDUMPCOMMENT("HWDeviceSyncObject for RT: %i\r\n", i);
@@ -275,7 +310,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT ROpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -283,7 +320,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -315,23 +354,37 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(IMG_UINT32),
0,
MAKEUNIQUETAG(psHWDstSyncListMemInfo));
+
+ /*
+ * Force the ROps2Complete value to 0.
+ */
+ PDUMPCOMMENT("Modify RT %d ROps2PendingVal in HWDevSyncList\r\n", i);
+ PDUMPMEM(&ui32ModifiedValue,
+ psHWDstSyncListMemInfo,
+ ui32ROps2Offset,
+ sizeof(IMG_UINT32),
+ 0,
+ MAKEUNIQUETAG(psHWDstSyncListMemInfo));
}
- #endif
+ #endif /* defined(PDUMP) */
}
else
{
psHWDeviceSyncList->asSyncData[i].sWriteOpsCompleteDevVAddr.uiAddr = 0;
psHWDeviceSyncList->asSyncData[i].sReadOpsCompleteDevVAddr.uiAddr = 0;
+ psHWDeviceSyncList->asSyncData[i].sReadOps2CompleteDevVAddr.uiAddr = 0;
psHWDeviceSyncList->asSyncData[i].ui32ReadOpsPendingVal = 0;
+ psHWDeviceSyncList->asSyncData[i].ui32ReadOps2PendingVal = 0;
psHWDeviceSyncList->asSyncData[i].ui32WriteOpsPendingVal = 0;
}
}
}
-
-
-
+ /*
+ NOTE: THIS MUST BE THE LAST THING WRITTEN TO THE TA COMMAND!
+ Set the ready for so the uKernel will process the command.
+ */
psTACmd->ui32CtrlFlags |= SGXMKIF_CMDTA_CTRLFLAGS_READY;
#if defined(PDUMP)
@@ -355,7 +408,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-SRC ROpsComplete\r\n", i);
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -363,7 +418,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-SRC WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -406,7 +463,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-DST ROpsComplete\r\n", i);
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -414,7 +473,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT TA-DST WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -457,7 +518,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT 3D-SRC ROpsComplete\r\n", i);
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -465,7 +528,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT 3D-SRC WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -499,7 +564,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
0,
MAKEUNIQUETAG(psCCBMemInfo));
}
-#else
+#else/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
IMG_UINT32 ui32ModifiedValue;
@@ -508,7 +573,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
if ((psSyncInfo->psSyncData->ui32LastOpDumpVal == 0) &&
(psSyncInfo->psSyncData->ui32LastReadOpDumpVal == 0))
{
-
+ /*
+ * Init the ROpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT ROpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -516,7 +583,9 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(psSyncInfo->psSyncData->ui32ReadOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
-
+ /*
+ * Init the WOpsComplete value to 0.
+ */
PDUMPCOMMENT("Init RT WOpsComplete\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psSyncInfo->psSyncDataMemInfoKM,
@@ -524,6 +593,16 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
sizeof(psSyncInfo->psSyncData->ui32WriteOpsComplete),
0,
MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
+ /*
+ * Init the ROps2Complete value to 0.
+ */
+ PDUMPCOMMENT("Init RT WOpsComplete\r\n");
+ PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
+ psSyncInfo->psSyncDataMemInfoKM,
+ offsetof(PVRSRV_SYNC_DATA, ui32ReadOps2Complete),
+ sizeof(psSyncInfo->psSyncData->ui32ReadOps2Complete),
+ 0,
+ MAKEUNIQUETAG(psSyncInfo->psSyncDataMemInfoKM));
}
psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
@@ -581,7 +660,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psSyncInfo->psSyncData->ui32LastReadOpDumpVal++;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
{
@@ -611,7 +690,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
#endif
}
}
-#endif
+#endif /* defined(PDUMP) */
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_CMD_END,
KICK_TOKEN_DOKICK);
@@ -623,7 +702,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
{
for (i=0; i < psCCBKick->ui32NumDstSyncObjects; i++)
{
-
+ /* Client will retry, so undo the write ops pending increment done above. */
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->pahDstSyncHandles[i];
if (psSyncInfo)
@@ -655,13 +734,13 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsPending--;
}
-#else
+#else/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsPending--;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
PVR_TTRACE(PVRSRV_TRACE_GROUP_KICK, PVRSRV_TRACE_CLASS_FUNCTION_EXIT,
KICK_TOKEN_DOKICK);
@@ -679,7 +758,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
#if defined(NO_HARDWARE)
-
+ /* TA/3D dependency */
if (psCCBKick->hTA3DSyncInfo)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psCCBKick->hTA3DSyncInfo;
@@ -704,12 +783,12 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
}
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32NumTAStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->asTAStatusUpdate[i].hKernelMemInfo;
-
+ /* derive offset into meminfo and write the status value */
*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ (psTACmd->sCtlTAStatusInfo[i].sStatusDevAddr.uiAddr
- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtlTAStatusInfo[i].ui32StatusValue;
@@ -720,7 +799,7 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
}
#if defined(SUPPORT_SGX_GENERALISED_SYNCOBJECTS)
-
+ /* SRC and DST dependencies */
for (i=0; i<psCCBKick->ui32NumTASrcSyncs; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahTASrcKernelSyncInfo[i];
@@ -736,14 +815,14 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ah3DSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
}
-#else
-
+#else/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
+ /* texture dependencies */
for (i=0; i<psCCBKick->ui32NumSrcSyncs; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *) psCCBKick->ahSrcKernelSyncInfo[i];
psSyncInfo->psSyncData->ui32ReadOpsComplete = psSyncInfo->psSyncData->ui32ReadOpsPending;
}
-#endif
+#endif/* SUPPORT_SGX_GENERALISED_SYNCOBJECTS */
if (psCCBKick->bTerminateOrAbort)
{
@@ -761,12 +840,12 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
}
}
-
+ /* Copy status vals over */
for (i = 0; i < psCCBKick->ui32Num3DStatusVals; i++)
{
#if defined(SUPPORT_SGX_NEW_STATUS_VALS)
PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo = (PVRSRV_KERNEL_MEM_INFO*)psCCBKick->as3DStatusUpdate[i].hKernelMemInfo;
-
+ /* derive offset into meminfo and write the status value */
*(IMG_UINT32*)((IMG_UINTPTR_T)psKernelMemInfo->pvLinAddrKM
+ (psTACmd->sCtl3DStatusInfo[i].sStatusDevAddr.uiAddr
- psKernelMemInfo->sDevVAddr.uiAddr)) = psTACmd->sCtl3DStatusInfo[i].ui32StatusValue;
@@ -782,3 +861,6 @@ PVRSRV_ERROR SGXDoKickKM(IMG_HANDLE hDevHandle, SGX_CCB_KICK *psCCBKick)
return eError;
}
+/******************************************************************************
+ End of file (sgxkick.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxpower.c b/sgx/services4/srvkm/devices/sgx/sgxpower.c
index 3947cdd..3e7aa6c 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxpower.c
+++ b/sgx/services4/srvkm/devices/sgx/sgxpower.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific power routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <stddef.h>
@@ -39,9 +55,10 @@ static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode,
SGX_TIMING_INFORMATION *psSGXTimingInfo,
IMG_HANDLE *phTimer)
{
-
-
-
+ /*
+ Install timer callback for HW recovery at 50 times lower
+ frequency than the microkernel timer.
+ */
*phTimer = OSAddTimer(SGXOSTimer, psDeviceNode,
1000 * 50 / psSGXTimingInfo->ui32uKernelFreq);
if(*phTimer == IMG_NULL)
@@ -52,9 +69,23 @@ static PVRSRV_ERROR SGXAddTimer(PVRSRV_DEVICE_NODE *psDeviceNode,
return PVRSRV_OK;
}
-#endif
+#endif /* SUPPORT_HW_RECOVERY*/
+
+
+/*!
+******************************************************************************
+
+ @Function SGXUpdateTimingInfo
+
+ @Description
+
+ Derives the microkernel timing info from the system-supplied values
+ @Input psDeviceNode : SGX Device node
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
@@ -86,8 +117,9 @@ static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
ui32OlduKernelFreq = psDevInfo->ui32CoreClockSpeed / psDevInfo->ui32uKernelTimerClock;
if (ui32OlduKernelFreq != psSGXTimingInfo->ui32uKernelFreq)
{
-
-
+ /*
+ The ukernel timer frequency has changed.
+ */
IMG_HANDLE hNewTimer;
eError = SGXAddTimer(psDeviceNode, psSGXTimingInfo, &hNewTimer);
@@ -102,7 +134,7 @@ static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
}
else
{
-
+ /* Failed to allocate the new timer, leave the old one. */
}
}
}
@@ -118,13 +150,13 @@ static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
psDevInfo->psSGXHostCtl->ui32HWRecoverySampleRate =
psSGXTimingInfo->ui32uKernelFreq / psSGXTimingInfo->ui32HWRecoveryFreq;
}
-#endif
+#endif /* SUPPORT_HW_RECOVERY*/
-
+ /* Copy the SGX clock speed for use in the kernel */
psDevInfo->ui32CoreClockSpeed = psSGXTimingInfo->ui32CoreClockSpeed;
psDevInfo->ui32uKernelTimerClock = psSGXTimingInfo->ui32CoreClockSpeed / psSGXTimingInfo->ui32uKernelFreq;
-
+ /* FIXME: no need to duplicate - remove it from psDevInfo */
psDevInfo->psSGXHostCtl->ui32uKernelTimerClock = psDevInfo->ui32uKernelTimerClock;
#if defined(PDUMP)
PDUMPCOMMENT("Host Control - Microkernel clock");
@@ -132,19 +164,20 @@ static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
offsetof(SGXMKIF_HOST_CTL, ui32uKernelTimerClock),
sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
+#endif /* PDUMP */
if (psSGXTimingInfo->bEnableActivePM)
{
ui32ActivePowManSampleRate =
psSGXTimingInfo->ui32uKernelFreq * psSGXTimingInfo->ui32ActivePowManLatencyms / 1000;
-
-
-
-
-
-
-
+ /*
+ ui32ActivePowerCounter has the value 0 when SGX is not idle.
+ When SGX becomes idle, the value of ui32ActivePowerCounter is changed from 0 to ui32ActivePowManSampleRate.
+ The ukernel timer routine decrements the value of ui32ActivePowerCounter if it is not 0.
+ When the ukernel timer decrements ui32ActivePowerCounter from 1 to 0, the ukernel timer will
+ request power down.
+ Therefore the minimum value of ui32ActivePowManSampleRate is 1.
+ */
ui32ActivePowManSampleRate += 1;
}
else
@@ -158,12 +191,26 @@ static PVRSRV_ERROR SGXUpdateTimingInfo(PVRSRV_DEVICE_NODE *psDeviceNode)
offsetof(SGXMKIF_HOST_CTL, ui32ActivePowManSampleRate),
sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
-#endif
+#endif /* PDUMP */
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function SGXStartTimer
+
+ @Description
+
+ Start the microkernel timer
+
+ @Input psDevInfo : SGX Device Info
+
+ @Return IMG_VOID :
+
+******************************************************************************/
static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo)
{
#if defined(SUPPORT_HW_RECOVERY)
@@ -176,10 +223,27 @@ static IMG_VOID SGXStartTimer(PVRSRV_SGXDEV_INFO *psDevInfo)
}
#else
PVR_UNREFERENCED_PARAMETER(psDevInfo);
- #endif
+ #endif /* SUPPORT_HW_RECOVERY */
}
+/*!
+******************************************************************************
+
+ @Function SGXPollForClockGating
+
+ @Description
+
+ Wait until the SGX core clocks have gated.
+
+ @Input psDevInfo : SGX Device Info
+ @Input ui32Register : Offset of register to poll
+ @Input ui32Register : Value of register to poll for
+ @Input pszComment : Description of poll
+
+ @Return IMG_VOID :
+
+******************************************************************************/
static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32Register,
IMG_UINT32 ui32RegisterValue,
@@ -193,7 +257,7 @@ static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(NO_HARDWARE)
PVR_ASSERT(psDevInfo != IMG_NULL);
-
+ /* PRQA S 0505 1 */ /* QAC does not like assert() */
if (PollForValueKM((IMG_UINT32 *)psDevInfo->pvRegsBaseKM + (ui32Register >> 2),
0,
ui32RegisterValue,
@@ -202,15 +266,32 @@ static IMG_VOID SGXPollForClockGating (PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_FALSE) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXPollForClockGating: %s failed.", pszComment));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
}
- #endif
+ #endif /* NO_HARDWARE */
PDUMPCOMMENT("%s", pszComment);
PDUMPREGPOL(SGX_PDUMPREG_NAME, ui32Register, 0, ui32RegisterValue, PDUMP_POLL_OPERATOR_EQUAL);
}
+/*!
+******************************************************************************
+
+ @Function SGXPrePowerState
+
+ @Description
+
+ does necessary preparation before power state transition
+
+ @Input hDevHandle : SGX Device Node
+ @Input eNewPowerState : New power state
+ @Input eCurrentPowerState : Current power state
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
@@ -227,25 +308,25 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
IMG_UINT32 ui32CoresEnabled;
#if defined(SUPPORT_HW_RECOVERY)
-
+ /* Disable timer callback for HW recovery */
eError = OSDisableTimer(psDevInfo->hTimer);
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Failed to disable timer"));
return eError;
}
- #endif
+ #endif /* SUPPORT_HW_RECOVERY */
if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
{
-
+ /* Request the ukernel to idle SGX and save its state. */
ui32PowerCmd = PVRSRV_POWERCMD_POWEROFF;
ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_POWEROFF_COMPLETE;
PDUMPCOMMENT("SGX power off request");
}
else
{
-
+ /* Request the ukernel to idle SGX. */
ui32PowerCmd = PVRSRV_POWERCMD_IDLE;
ui32CompleteStatus = PVRSRV_USSE_EDM_POWMAN_IDLE_COMPLETE;
PDUMPCOMMENT("SGX idle request");
@@ -260,7 +341,7 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
return eError;
}
-
+ /* Wait for the ukernel to complete processing. */
#if !defined(NO_HARDWARE)
if (PollForValueKM(&psDevInfo->psSGXHostCtl->ui32PowerStatus,
ui32CompleteStatus,
@@ -270,9 +351,10 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
IMG_FALSE) != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXPrePowerState: Wait for SGX ukernel power transition failed."));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
}
- #endif
+ #endif /* NO_HARDWARE */
#if defined(PDUMP)
PDUMPCOMMENT("TA/3D CCB Control - Wait for power event on uKernel.");
@@ -283,7 +365,7 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
PDUMP_POLL_OPERATOR_EQUAL,
0,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
#if defined(SGX_FEATURE_MP)
ui32CoresEnabled = ((OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_CORE) & EUR_CR_MASTER_CORE_ENABLE_MASK) >> EUR_CR_MASTER_CORE_ENABLE_SHIFT) + 1;
@@ -293,7 +375,7 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
for (ui32Core = 0; ui32Core < ui32CoresEnabled; ui32Core++)
{
-
+ /* Wait for SGX clock gating. */
SGXPollForClockGating(psDevInfo,
SGX_MP_CORE_SELECT(psDevInfo->ui32ClkGateStatusReg, ui32Core),
psDevInfo->ui32ClkGateStatusMask,
@@ -301,7 +383,7 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
}
#if defined(SGX_FEATURE_MP)
-
+ /* Wait for SGX master clock gating. */
SGXPollForClockGating(psDevInfo,
psDevInfo->ui32MasterClkGateStatusReg,
psDevInfo->ui32MasterClkGateStatusMask,
@@ -311,11 +393,11 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
psDevInfo->ui32MasterClkGateStatus2Reg,
psDevInfo->ui32MasterClkGateStatus2Mask,
"Wait for SGX master clock gating (2)");
- #endif
+ #endif /* SGX_FEATURE_MP */
if (eNewPowerState == PVRSRV_DEV_POWER_STATE_OFF)
{
-
+ /* Finally, de-initialise some registers. */
eError = SGXDeinitialise(psDevInfo);
if (eError != PVRSRV_OK)
{
@@ -329,6 +411,22 @@ PVRSRV_ERROR SGXPrePowerState (IMG_HANDLE hDevHandle,
}
+/*!
+******************************************************************************
+
+ @Function SGXPostPowerState
+
+ @Description
+
+ does necessary preparation after power state transition
+
+ @Input hDevHandle : SGX Device Node
+ @Input eNewPowerState : New power state
+ @Input eCurrentPowerState : Current power state
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
PVRSRV_DEV_POWER_STATE eNewPowerState,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
@@ -341,7 +439,7 @@ PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
-
+ /* Reset the power manager flags. */
psSGXHostCtl->ui32PowerStatus = 0;
#if defined(PDUMP)
PDUMPCOMMENT("Host Control - Reset power status");
@@ -349,14 +447,17 @@ PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
offsetof(SGXMKIF_HOST_CTL, ui32PowerStatus),
sizeof(IMG_UINT32), PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psDevInfo->psKernelSGXHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
if (eCurrentPowerState == PVRSRV_DEV_POWER_STATE_OFF)
{
-
-
-
+ /*
+ Coming up from off, re-initialise SGX.
+ */
+ /*
+ Re-generate the timing data required by SGX.
+ */
eError = SGXUpdateTimingInfo(psDeviceNode);
if (eError != PVRSRV_OK)
{
@@ -364,8 +465,9 @@ PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
return eError;
}
-
-
+ /*
+ Run the SGX init script.
+ */
eError = SGXInitialise(psDevInfo, IMG_FALSE);
if (eError != PVRSRV_OK)
{
@@ -375,8 +477,9 @@ PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
}
else
{
-
-
+ /*
+ Coming up from idle, restart the ukernel.
+ */
SGXMKIF_COMMAND sCommand = {0};
sCommand.ui32Data[1] = PVRSRV_POWERCMD_RESUME;
@@ -395,6 +498,22 @@ PVRSRV_ERROR SGXPostPowerState (IMG_HANDLE hDevHandle,
}
+/*!
+******************************************************************************
+
+ @Function SGXPreClockSpeedChange
+
+ @Description
+
+ Does processing required before an SGX clock speed change.
+
+ @Input hDevHandle : SGX Device Node
+ @Input bIdleDevice : Whether the microkernel needs to be idled
+ @Input eCurrentPowerState : Power state of the device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
IMG_BOOL bIdleDevice,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
@@ -409,7 +528,9 @@ PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
{
if (bIdleDevice)
{
-
+ /*
+ * Idle SGX.
+ */
PDUMPSUSPEND();
eError = SGXPrePowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_IDLE,
@@ -430,6 +551,22 @@ PVRSRV_ERROR SGXPreClockSpeedChange (IMG_HANDLE hDevHandle,
}
+/*!
+******************************************************************************
+
+ @Function SGXPostClockSpeedChange
+
+ @Description
+
+ Does processing required after an SGX clock speed change.
+
+ @Input hDevHandle : SGX Device Node
+ @Input bIdleDevice : Whether the microkernel had been idled previously
+ @Input eCurrentPowerState : Power state of the device
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
IMG_BOOL bIdleDevice,
PVRSRV_DEV_POWER_STATE eCurrentPowerState)
@@ -444,8 +581,9 @@ PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
{
PVRSRV_ERROR eError;
-
-
+ /*
+ Re-generate the timing data required by SGX.
+ */
eError = SGXUpdateTimingInfo(psDeviceNode);
if (eError != PVRSRV_OK)
{
@@ -455,7 +593,9 @@ PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
if (bIdleDevice)
{
-
+ /*
+ * Resume SGX.
+ */
eError = SGXPostPowerState(hDevHandle, PVRSRV_DEV_POWER_STATE_ON,
PVRSRV_DEV_POWER_STATE_IDLE);
@@ -479,3 +619,6 @@ PVRSRV_ERROR SGXPostClockSpeedChange (IMG_HANDLE hDevHandle,
}
+/******************************************************************************
+ End of file (sgxpower.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxreset.c b/sgx/services4/srvkm/devices/sgx/sgxreset.c
index 519783f..35b63c9 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxreset.c
+++ b/sgx/services4/srvkm/devices/sgx/sgxreset.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific reset routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "sgxdefs.h"
#include "sgxmmu.h"
@@ -34,6 +50,20 @@
#include "pdump_km.h"
+/*!
+*******************************************************************************
+
+ @Function SGXInitClocks
+
+ @Description
+ Initialise the SGX clocks
+
+ @Input psDevInfo - device info. structure
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags)
{
@@ -41,7 +71,7 @@ IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
ui32RegVal = psDevInfo->ui32ClkGateCtl;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_CLKGATECTL, ui32RegVal);
@@ -55,6 +85,19 @@ IMG_VOID SGXInitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetInitBIFContexts
+
+ @Description
+ Initialise the BIF memory contexts
+
+ @Input psDevInfo - SGX Device Info
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags)
{
@@ -62,7 +105,7 @@ static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
ui32RegVal = 0;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
@@ -74,7 +117,7 @@ static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK_SET, ui32RegVal, ui32PDUMPFlags);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
-#endif
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the BIF directory list\r\n");
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
@@ -93,10 +136,23 @@ static IMG_VOID SGXResetInitBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, ui32DirListReg, ui32RegVal, ui32PDUMPFlags);
}
}
-#endif
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetSetupBIFContexts
+
+ @Description
+ Configure the BIF for the EDM context
+
+ @Input psDevInfo - SGX Device Info
+
+ @Return IMG_VOID
+
+******************************************************************************/
static IMG_VOID SGXResetSetupBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags)
{
@@ -104,37 +160,37 @@ static IMG_VOID SGXResetSetupBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
#if defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
-
+ /* Set up EDM for bank 0 to point at kernel context */
ui32RegVal = (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT);
#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
-
+ /* Set up 2D core for bank 0 to point at kernel context */
ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_2D_SHIFT);
- #endif
+ #endif /* SGX_FEATURE_2D_HARDWARE */
#if defined(FIX_HW_BRN_23410)
-
+ /* Set up TA core for bank 0 to point at kernel context to guarantee it is a valid context */
ui32RegVal |= (SGX_BIF_DIR_LIST_INDEX_EDM << EUR_CR_BIF_BANK0_INDEX_TA_SHIFT);
- #endif
+ #endif /* FIX_HW_BRN_23410 */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_BANK0, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Set up EDM requestor page table in BIF\r\n");
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_BANK0, ui32RegVal, ui32PDUMPFlags);
- #endif
+ #endif /* defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS) */
{
IMG_UINT32 ui32EDMDirListReg;
-
+ /* Set up EDM context with kernel page directory */
#if (SGX_BIF_DIR_LIST_INDEX_EDM == 0)
ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE0;
#else
-
+ /* Bases 0 and 1 are not necessarily contiguous */
ui32EDMDirListReg = EUR_CR_BIF_DIR_LIST_BASE1 + 4 * (SGX_BIF_DIR_LIST_INDEX_EDM - 1);
- #endif
+ #endif /* SGX_BIF_DIR_LIST_INDEX_EDM */
ui32RegVal = psDevInfo->sKernelPDDevPAddr.uiAddr >> SGX_MMU_PDE_ADDR_ALIGNSHIFT;
@@ -150,6 +206,23 @@ static IMG_VOID SGXResetSetupBIFContexts(PVRSRV_SGXDEV_INFO *psDevInfo,
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetSleep
+
+ @Description
+
+ Sleep for a short time to allow reset register writes to complete.
+ Required because no status registers are available to poll on.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+ @Input bPDump - Pdump the sleep
+
+ @Return Nothing
+
+******************************************************************************/
static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags,
IMG_BOOL bPDump)
@@ -161,14 +234,14 @@ static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32ReadRegister = EUR_CR_MASTER_SOFT_RESET;
#else
ui32ReadRegister = EUR_CR_SOFT_RESET;
- #endif
+ #endif /* SGX_FEATURE_MP */
#endif
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
-
+ /* Sleep for 100 SGX clocks */
SGXWaitClocks(psDevInfo, 100);
if (bPDump)
{
@@ -180,14 +253,32 @@ static IMG_VOID SGXResetSleep(PVRSRV_SGXDEV_INFO *psDevInfo,
}
#if defined(EMULATOR)
-
-
+ /*
+ Read a register to make sure we wait long enough on the emulator...
+ */
OSReadHWReg(psDevInfo->pvRegsBaseKM, ui32ReadRegister);
#endif
}
#if !defined(SGX_FEATURE_MP)
+/*!
+*******************************************************************************
+
+ @Function SGXResetSoftReset
+
+ @Description
+
+ Write to the SGX soft reset register.
+
+ @Input psDevInfo - SGX Device Info
+ @Input bResetBIF - Include the BIF in the soft reset
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+ @Input bPDump - Pdump the sleep
+
+ @Return Nothing
+
+******************************************************************************/
static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bResetBIF,
IMG_UINT32 ui32PDUMPFlags,
@@ -196,13 +287,14 @@ static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32SoftResetRegVal;
ui32SoftResetRegVal =
-
+ /* add common reset bits: */
EUR_CR_SOFT_RESET_DPM_RESET_MASK |
EUR_CR_SOFT_RESET_TA_RESET_MASK |
EUR_CR_SOFT_RESET_USE_RESET_MASK |
EUR_CR_SOFT_RESET_ISP_RESET_MASK |
EUR_CR_SOFT_RESET_TSP_RESET_MASK;
+/* add conditional reset bits: */
#ifdef EUR_CR_SOFT_RESET_TWOD_RESET_MASK
ui32SoftResetRegVal |= EUR_CR_SOFT_RESET_TWOD_RESET_MASK;
#endif
@@ -254,7 +346,7 @@ static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
if (bResetBIF)
{
@@ -269,13 +361,28 @@ static IMG_VOID SGXResetSoftReset(PVRSRV_SGXDEV_INFO *psDevInfo,
}
+/*!
+*******************************************************************************
+
+ @Function SGXResetInvalDC
+
+ @Description
+
+ Invalidate the BIF Directory Cache and wait for the operation to complete.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return Nothing
+
+******************************************************************************/
static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32PDUMPFlags,
IMG_BOOL bPDump)
{
IMG_UINT32 ui32RegVal;
-
+ /* Invalidate BIF Directory cache. */
#if defined(EUR_CR_BIF_CTRL_INVAL)
ui32RegVal = EUR_CR_BIF_CTRL_INVAL_ALL_MASK;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL_INVAL, ui32RegVal);
@@ -302,9 +409,10 @@ static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(SGX_FEATURE_MULTIPLE_MEM_CONTEXTS)
{
-
-
-
+ /*
+ Wait for the DC invalidate to complete - indicated by
+ outstanding reads reaching zero.
+ */
if (PollForValueKM((IMG_UINT32 *)((IMG_UINT8*)psDevInfo->pvRegsBaseKM + EUR_CR_BIF_MEM_REQ_STAT),
0,
EUR_CR_BIF_MEM_REQ_STAT_READS_MASK,
@@ -321,11 +429,28 @@ static IMG_VOID SGXResetInvalDC(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMPREGPOLWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_REQ_STAT, 0, EUR_CR_BIF_MEM_REQ_STAT_READS_MASK, ui32PDUMPFlags, PDUMP_POLL_OPERATOR_EQUAL);
}
}
-#endif
+#endif /* SGX_FEATURE_MULTIPLE_MEM_CONTEXTS */
}
-#endif
+#endif /* SGX_FEATURE_MP */
+
+
+/*!
+*******************************************************************************
+ @Function SGXReset
+ @Description
+
+ Reset chip
+
+ @Input psDevInfo - device info. structure
+ @Input bHardwareRecovery - true if recovering powered hardware,
+ false if powering up
+ @Input ui32PDUMPFlags - flags to control PDUMP output
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_BOOL bHardwareRecovery,
IMG_UINT32 ui32PDUMPFlags)
@@ -340,12 +465,12 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX reset sequence\r\n");
#if defined(FIX_HW_BRN_23944)
-
+ /* Pause the BIF. */
ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
@@ -355,7 +480,7 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
if (ui32RegVal & ui32BifFaultMask)
{
-
+ /* Page fault needs to be cleared before resetting the BIF. */
ui32RegVal = EUR_CR_BIF_CTRL_PAUSE_MASK | EUR_CR_BIF_CTRL_CLEAR_FAULT_MASK;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_CTRL, ui32RegVal, ui32PDUMPFlags);
@@ -368,17 +493,18 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
}
-#endif
+#endif /* defined(FIX_HW_BRN_23944) */
-
+ /* Reset all including BIF */
SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_TRUE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
-
-
+ /*
+ Initialise the BIF state.
+ */
#if defined(SGX_FEATURE_36BIT_MMU)
-
+ /* enable 36bit addressing mode if the MMU supports it*/
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_36BIT_ADDRESSING, EUR_CR_BIF_36BIT_ADDRESSING_ENABLE_MASK, ui32PDUMPFlags);
#endif
@@ -386,57 +512,60 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
SGXResetInitBIFContexts(psDevInfo, ui32PDUMPFlags);
#if defined(EUR_CR_BIF_MEM_ARB_CONFIG)
-
-
+ /*
+ Initialise the memory arbiter to its default state
+ */
ui32RegVal = (12UL << EUR_CR_BIF_MEM_ARB_CONFIG_PAGE_SIZE_SHIFT) |
(7UL << EUR_CR_BIF_MEM_ARB_CONFIG_BEST_CNT_SHIFT) |
(12UL << EUR_CR_BIF_MEM_ARB_CONFIG_TTE_THRESH_SHIFT);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_MEM_ARB_CONFIG, ui32RegVal, ui32PDUMPFlags);
-#endif
+#endif /* EUR_CR_BIF_MEM_ARB_CONFIG */
#if defined(SGX_FEATURE_SYSTEM_CACHE)
#if defined(SGX_BYPASS_SYSTEM_CACHE)
-
+ /* set the SLC to bypass all accesses */
ui32RegVal = MNE_CR_CTRL_BYPASS_ALL_MASK;
#else
#if defined(FIX_HW_BRN_26620)
ui32RegVal = 0;
#else
-
+ /* set the SLC to bypass cache-coherent accesses */
ui32RegVal = MNE_CR_CTRL_BYP_CC_MASK;
#endif
#if defined(FIX_HW_BRN_34028)
-
+ /* Bypass the MNE for the USEC requester */
ui32RegVal |= (8 << MNE_CR_CTRL_BYPASS_SHIFT);
#endif
- #endif
+ #endif /* SGX_BYPASS_SYSTEM_CACHE */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, MNE_CR_CTRL, ui32RegVal);
PDUMPREG(SGX_PDUMPREG_NAME, MNE_CR_CTRL, ui32RegVal);
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
if (bHardwareRecovery)
{
-
-
-
-
-
-
-
+ /*
+ Set all requestors to the dummy PD which forces all memory
+ accesses to page fault.
+ This enables us to flush out BIF requests from parts of SGX
+ which do not have their own soft reset.
+ Note: sBIFResetPDDevPAddr.uiAddr is a relative address (2GB max)
+ MSB is the bus master flag; 1 == enabled
+ */
ui32RegVal = (IMG_UINT32)psDevInfo->sBIFResetPDDevPAddr.uiAddr;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_DIR_LIST_BASE0, ui32RegVal);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Bring BIF out of reset. */
SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
-
+ /*
+ Check for a page fault from parts of SGX which do not have a reset.
+ */
for (;;)
{
IMG_UINT32 ui32BifIntStat = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_INT_STAT);
@@ -448,18 +577,19 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
break;
}
-
-
-
+ /*
+ There is a page fault, so reset the BIF again, map in the dummy page,
+ bring the BIF up and invalidate the Directory Cache.
+ */
sBifFault.uiAddr = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_FAULT);
PVR_DPF((PVR_DBG_WARNING, "SGXReset: Page fault 0x%x/0x%x", ui32BifIntStat, sBifFault.uiAddr));
ui32PDIndex = sBifFault.uiAddr >> (SGX_MMU_PAGE_SHIFT + SGX_MMU_PT_SHIFT);
ui32PTIndex = (sBifFault.uiAddr & SGX_MMU_PT_MASK) >> SGX_MMU_PAGE_SHIFT;
-
+ /* Put the BIF into reset. */
SGXResetSoftReset(psDevInfo, IMG_TRUE, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Map in the dummy page. */
psDevInfo->pui32BIFResetPD[ui32PDIndex] = (psDevInfo->sBIFResetPTDevPAddr.uiAddr
>>SGX_MMU_PDE_ADDR_ALIGNSHIFT)
| SGX_MMU_PDE_PAGE_SIZE_4K
@@ -468,7 +598,7 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
>>SGX_MMU_PTE_ADDR_ALIGNSHIFT)
| SGX_MMU_PTE_VALID;
-
+ /* Clear outstanding events. */
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_HOST_CLEAR, ui32RegVal);
ui32RegVal = OSReadHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_EVENT_STATUS2);
@@ -476,50 +606,51 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Bring the BIF out of reset. */
SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_FALSE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Invalidate Directory Cache. */
SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
-
+ /* Unmap the dummy page and try again. */
psDevInfo->pui32BIFResetPD[ui32PDIndex] = 0;
psDevInfo->pui32BIFResetPT[ui32PTIndex] = 0;
}
}
else
{
-
+ /* Bring BIF out of reset. */
SGXResetSoftReset(psDevInfo, IMG_FALSE, ui32PDUMPFlags, IMG_TRUE);
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_FALSE);
}
-
-
+ /*
+ Initialise the BIF memory contexts before bringing the rest of SGX out of reset.
+ */
SGXResetSetupBIFContexts(psDevInfo, ui32PDUMPFlags);
#if defined(SGX_FEATURE_2D_HARDWARE) && !defined(SGX_FEATURE_PTLA)
-
+ /* check that the heap base has the right alignment (1Mb) */
#if ((SGX_2D_HEAP_BASE & ~EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK) != 0)
#error "SGXReset: SGX_2D_HEAP_BASE doesn't match EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK alignment"
#endif
-
+ /* Set up 2D requestor base */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_BIF_TWOD_REQ_BASE, SGX_2D_HEAP_BASE, ui32PDUMPFlags);
#endif
-
+ /* Invalidate BIF Directory cache. */
SGXResetInvalDC(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
PVR_DPF((PVR_DBG_MESSAGE,"Soft Reset of SGX"));
-
+ /* Take chip out of reset */
ui32RegVal = 0;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_SOFT_RESET, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_SOFT_RESET, ui32RegVal, ui32PDUMPFlags);
-
+ /* wait a bit */
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX reset sequence\r\n");
@@ -534,17 +665,21 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
#if !defined(PDUMP)
PVR_UNREFERENCED_PARAMETER(ui32PDUMPFlags);
-#endif
+#endif /* PDUMP */
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Start of SGX MP reset sequence\r\n");
-
+ /* Put hydra into soft reset */
ui32RegVal = EUR_CR_MASTER_SOFT_RESET_BIF_RESET_MASK |
EUR_CR_MASTER_SOFT_RESET_IPF_RESET_MASK |
EUR_CR_MASTER_SOFT_RESET_DPM_RESET_MASK |
- EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK |
EUR_CR_MASTER_SOFT_RESET_VDM_RESET_MASK;
+ if (bHardwareRecovery)
+ {
+ ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_MCI_RESET_MASK;
+ }
+
#if defined(SGX_FEATURE_PTLA)
ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_MASK;
#endif
@@ -552,7 +687,7 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_SLC_RESET_MASK;
#endif
-
+ /* Hard reset the slave cores */
ui32RegVal |= EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(0) |
EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(1) |
EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(2) |
@@ -580,6 +715,9 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
#if defined(PVR_SLC_8KB_ADDRESS_MODE)
(4 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
#endif
+ #if defined(FIX_HW_BRN_33809)
+ (2 << EUR_CR_MASTER_SLC_CTRL_ADDR_DECODE_MODE_SHIFT) |
+ #endif
(0xC << EUR_CR_MASTER_SLC_CTRL_ARB_PAGE_SIZE_SHIFT);
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC control\r\n");
@@ -596,15 +734,15 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_USE3_MASK |
EUR_CR_MASTER_SLC_CTRL_BYPASS_REQ_TA_MASK;
#endif
- #endif
+ #endif /* SGX_BYPASS_SYSTEM_CACHE */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Initialise the hydra SLC bypass control\r\n");
PDUMPREG(SGX_PDUMPREG_NAME, EUR_CR_MASTER_SLC_CTRL_BYPASS, ui32RegVal);
-#endif
+#endif /* SGX_FEATURE_SYSTEM_CACHE */
SGXResetSleep(psDevInfo, ui32PDUMPFlags, IMG_TRUE);
-
+ /* Remove the resets */
ui32RegVal = 0;
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_SOFT_RESET, ui32RegVal);
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "Remove the resets from all of SGX\r\n");
@@ -621,32 +759,32 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_31620) || defined(FIX_HW_BRN_31671) || defined(FIX_HW_BRN_32085)
#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
-
+ /* disable prefetch */
ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
#else
ui32RegVal = (1<<EUR_CR_MASTER_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK;
#endif
#if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
-
+ /* enable the DC TLB */
ui32RegVal |= EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
#endif
-
+ /* Master bank */
OSWriteHWReg(psDevInfo->pvRegsBaseKM, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal);
PDUMPREGWITHFLAGS(SGX_PDUMPREG_NAME, EUR_CR_MASTER_BIF_MMU_CTRL, ui32RegVal, ui32PDUMPFlags);
#if defined(FIX_HW_BRN_31278) || defined(FIX_HW_BRN_32085)
-
+ /* disable prefetch */
ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT);
#else
ui32RegVal = (1<<EUR_CR_BIF_MMU_CTRL_ADDR_HASH_MODE_SHIFT) | EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK;
#endif
#if !defined(FIX_HW_BRN_31620) && !defined(FIX_HW_BRN_31671)
-
+ /* enable the DC TLB */
ui32RegVal |= EUR_CR_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK;
#endif
-
+ /* Per-core */
{
IMG_UINT32 ui32Core;
@@ -663,6 +801,9 @@ IMG_VOID SGXReset(PVRSRV_SGXDEV_INFO *psDevInfo,
PDUMPCOMMENTWITHFLAGS(ui32PDUMPFlags, "End of SGX MP reset sequence\r\n");
}
-#endif
+#endif /* SGX_FEATURE_MP */
+/******************************************************************************
+ End of file (sgxreset.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxtransfer.c b/sgx/services4/srvkm/devices/sgx/sgxtransfer.c
index bde6fc6..e85015d 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxtransfer.c
+++ b/sgx/services4/srvkm/devices/sgx/sgxtransfer.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific transfer queue routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if defined(TRANSFER_QUEUE)
@@ -68,7 +84,11 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
#if defined(PDUMP)
IMG_BOOL bPersistentProcess = IMG_FALSE;
-
+ /*
+ * For persistent processes, the HW kicks should not go into the
+ * extended init phase; only keep memory transactions from the
+ * window system which are necessary to run the client app.
+ */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc != IMG_NULL)
@@ -76,7 +96,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
bPersistentProcess = psPerProc->bPDumpPersistent;
}
}
-#endif
+#endif /* PDUMP */
#if defined(FIX_HW_BRN_31620)
hDevMemContext = psKick->hDevMemContext;
#endif
@@ -89,8 +109,8 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
TRANSFER_TOKEN_SUBMIT);
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
+ /* override QAC warning about stricter alignment */
+ /* PRQA S 3305 1 */
psSharedTransferCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_TRANSFERCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
PVR_TTRACE(PVRSRV_TRACE_GROUP_TRANSFER, PVRSRV_TRACE_CLASS_CMD_START, TRANSFER_TOKEN_SUBMIT);
@@ -135,7 +155,9 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
psSharedTransferCmd->s3DSyncReadOpsCompleteDevVAddr.uiAddr = 0;
}
-
+ /* filter out multiple occurrences of the same sync object from srcs or dests
+ * note : the same sync can still be used to synchronize both src and dst.
+ */
for (loop = 0; loop < MIN(SGX_MAX_TRANSFER_SYNC_OPS, psKick->ui32NumSrcSync); loop++)
{
IMG_UINT32 i;
@@ -158,10 +180,6 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
}
if (uiSrcSyncEnable & (1 << loop))
{
- if (psMySyncInfo->hSmartCache)
- {
- PVRMMapPrepareCpuToGpu(psMySyncInfo->hSmartCache);
- }
ui32RealSrcSyncNum++;
}
}
@@ -187,11 +205,6 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
}
if (uiDstSyncEnable & (1 << loop))
{
- if (psMySyncInfo->hSmartCache)
- {
- /* TODO this should happen after GPU is done? */
- PVRMMapPrepareGpuToCpu(psMySyncInfo->hSmartCache);
- }
ui32RealDstSyncNum++;
}
}
@@ -229,20 +242,29 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahDstSyncInfo[loop];
+ psSyncInfo->psSyncData->ui64LastWrite = ui64KickCount;
+
PVR_TTRACE_SYNC_OBJECT(PVRSRV_TRACE_GROUP_TRANSFER, TRANSFER_TOKEN_DST_SYNC,
psSyncInfo, PVRSRV_SYNCOP_SAMPLE);
psSharedTransferCmd->asDstSyncs[i].ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
psSharedTransferCmd->asDstSyncs[i].ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ psSharedTransferCmd->asDstSyncs[i].ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
psSharedTransferCmd->asDstSyncs[i].sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
psSharedTransferCmd->asDstSyncs[i].sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ psSharedTransferCmd->asDstSyncs[i].sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
i++;
}
}
PVR_ASSERT(i == ui32RealDstSyncNum);
-
+ /*
+ * We allow source and destination sync objects to be the
+ * same, which is why the read/write pending updates are delayed
+ * until the transfer command has been updated with the current
+ * values from the objects.
+ */
for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
{
if (uiSrcSyncEnable & (1 << loop))
@@ -284,7 +306,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
{
psSyncInfo = psKick->ahSrcSyncInfo[loop];
- PDUMPCOMMENT("Hack src surface write op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface write op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
@@ -292,7 +314,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack src surface read op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface read op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asSrcSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
@@ -308,9 +330,10 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
{
if (uiDstSyncEnable & (1 << loop))
{
+ IMG_UINT32 ui32PDumpReadOp2 = 0;
psSyncInfo = psKick->ahDstSyncInfo[loop];
- PDUMPCOMMENT("Hack dest surface write op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface write op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32WriteOpsPendingVal)),
@@ -318,18 +341,31 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack dest surface read op in transfer cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface read op in transfer cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOpsPendingVal)),
sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
+
+ PDUMPCOMMENT("Tweak dest surface read op2 in transfer cmd\r\n");
+ PDUMPMEM(&ui32PDumpReadOp2,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)(offsetof(SGXMKIF_TRANSFERCMD_SHARED, asDstSyncs) + i * sizeof(PVRSRV_DEVICE_SYNC_OBJECT) + offsetof(PVRSRV_DEVICE_SYNC_OBJECT, ui32ReadOps2PendingVal)),
+ sizeof(ui32PDumpReadOp2),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
i++;
}
}
-
+ /*
+ * We allow the first source and destination sync objects to be the
+ * same, which is why the read/write pending updates are delayed
+ * until the transfer command has been updated with the current
+ * values from the objects.
+ */
for (loop = 0; loop < (psKick->ui32NumSrcSync); loop++)
{
if (uiSrcSyncEnable & (1 << loop))
@@ -390,7 +426,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
if (eError == PVRSRV_ERROR_RETRY)
{
-
+ /* Client will retry, so undo the sync ops pending increment(s) done above. */
if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_KEEPPENDING) == 0UL)
{
for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
@@ -425,14 +461,14 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
}
}
-
+ /* Command needed to be synchronised with the TA? */
if (psKick->hTASyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
psSyncInfo->psSyncData->ui32WriteOpsPending--;
}
-
+ /* Command needed to be synchronised with the 3D? */
if (psKick->h3DSyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
@@ -452,7 +488,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmitTransferKM(IMG_HANDLE hDevHandle, PVRSRV_TRANSF
#if defined(NO_HARDWARE)
if ((psKick->ui32Flags & SGXMKIF_TQFLAGS_NOSYNCUPDATE) == 0)
{
-
+ /* Update sync objects pretending that we have done the job*/
for (loop = 0; loop < psKick->ui32NumSrcSync; loop++)
{
if (uiSrcSyncEnable & (1 << loop))
@@ -508,7 +544,11 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
IMG_HANDLE hDevMemContext = IMG_NULL;
#if defined(PDUMP)
IMG_BOOL bPersistentProcess = IMG_FALSE;
-
+ /*
+ * For persistent processes, the HW kicks should not go into the
+ * extended init phase; only keep memory transactions from the
+ * window system which are necessary to run the client app.
+ */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc != IMG_NULL)
@@ -516,7 +556,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
bPersistentProcess = psPerProc->bPDumpPersistent;
}
}
-#endif
+#endif /* PDUMP */
#if defined(FIX_HW_BRN_31620)
hDevMemContext = psKick->hDevMemContext;
#endif
@@ -526,13 +566,13 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
PVR_DPF((PVR_DBG_ERROR, "SGXSubmit2DKM: Invalid CCB offset"));
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
+ /* override QAC warning about stricter alignment */
+ /* PRQA S 3305 1 */
ps2DCmd = CCB_DATA_FROM_OFFSET(SGXMKIF_2DCMD_SHARED, psCCBMemInfo, psKick, ui32SharedCmdCCBOffset);
OSMemSet(ps2DCmd, 0, sizeof(*ps2DCmd));
-
+ /* Command needs to be synchronised with the TA? */
if (psKick->hTASyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
@@ -544,7 +584,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
ps2DCmd->sTASyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
}
-
+ /* Command needs to be synchronised with the 3D? */
if (psKick->h3DSyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
@@ -556,7 +596,12 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
ps2DCmd->s3DSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
}
-
+ /*
+ * We allow the first source and destination sync objects to be the
+ * same, which is why the read/write pending updates are delayed
+ * until the transfer command has been updated with the current
+ * values from the objects.
+ */
ps2DCmd->ui32NumSrcSync = psKick->ui32NumSrcSync;
for (i = 0; i < psKick->ui32NumSrcSync; i++)
{
@@ -575,12 +620,14 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
ps2DCmd->sDstSyncData.ui32WriteOpsPendingVal = psSyncInfo->psSyncData->ui32WriteOpsPending;
ps2DCmd->sDstSyncData.ui32ReadOpsPendingVal = psSyncInfo->psSyncData->ui32ReadOpsPending;
+ ps2DCmd->sDstSyncData.ui32ReadOps2PendingVal = psSyncInfo->psSyncData->ui32ReadOps2Pending;
ps2DCmd->sDstSyncData.sWriteOpsCompleteDevVAddr = psSyncInfo->sWriteOpsCompleteDevVAddr;
ps2DCmd->sDstSyncData.sReadOpsCompleteDevVAddr = psSyncInfo->sReadOpsCompleteDevVAddr;
+ ps2DCmd->sDstSyncData.sReadOps2CompleteDevVAddr = psSyncInfo->sReadOps2CompleteDevVAddr;
}
-
+ /* Read/Write ops pending updates, delayed from above */
for (i = 0; i < psKick->ui32NumSrcSync; i++)
{
psSyncInfo = psKick->ahSrcSyncInfo[i];
@@ -598,7 +645,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
|| ((psKick->ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
&& (bPersistentProcess == IMG_FALSE) )
{
-
+ /* Pdump the command from the per context CCB */
PDUMPCOMMENT("Shared part of 2D command\r\n");
PDUMPMEM(ps2DCmd,
psCCBMemInfo,
@@ -611,7 +658,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
{
psSyncInfo = psKick->ahSrcSyncInfo[i];
- PDUMPCOMMENT("Hack src surface write op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface write op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32WriteOpsPendingVal),
@@ -619,7 +666,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack src surface read op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak src surface read op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sSrcSyncData[i].ui32ReadOpsPendingVal),
@@ -630,9 +677,10 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
if (psKick->hDstSyncInfo != IMG_NULL)
{
+ IMG_UINT32 ui32PDumpReadOp2 = 0;
psSyncInfo = psKick->hDstSyncInfo;
- PDUMPCOMMENT("Hack dest surface write op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface write op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32WriteOpsPendingVal),
@@ -640,16 +688,23 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
- PDUMPCOMMENT("Hack dest surface read op in 2D cmd\r\n");
+ PDUMPCOMMENT("Tweak dest surface read op in 2D cmd\r\n");
PDUMPMEM(&psSyncInfo->psSyncData->ui32LastReadOpDumpVal,
psCCBMemInfo,
psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOpsPendingVal),
sizeof(psSyncInfo->psSyncData->ui32LastReadOpDumpVal),
psKick->ui32PDumpFlags,
MAKEUNIQUETAG(psCCBMemInfo));
+ PDUMPCOMMENT("Tweak dest surface read op2 in 2D cmd\r\n");
+ PDUMPMEM(&ui32PDumpReadOp2,
+ psCCBMemInfo,
+ psKick->ui32CCBDumpWOff + (IMG_UINT32)offsetof(SGXMKIF_2DCMD_SHARED, sDstSyncData.ui32ReadOps2PendingVal),
+ sizeof(ui32PDumpReadOp2),
+ psKick->ui32PDumpFlags,
+ MAKEUNIQUETAG(psCCBMemInfo));
}
-
+ /* Read/Write ops pending updates, delayed from above */
for (i = 0; i < psKick->ui32NumSrcSync; i++)
{
psSyncInfo = psKick->ahSrcSyncInfo[i];
@@ -670,8 +725,9 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
if (eError == PVRSRV_ERROR_RETRY)
{
-
-
+ /* Client will retry, so undo the write ops pending increment
+ done above.
+ */
#if defined(PDUMP)
if (PDumpIsCaptureFrameKM())
{
@@ -701,7 +757,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
psSyncInfo->psSyncData->ui32WriteOpsPending--;
}
-
+ /* Command needed to be synchronised with the TA? */
if (psKick->hTASyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->hTASyncInfo;
@@ -709,7 +765,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
psSyncInfo->psSyncData->ui32WriteOpsPending--;
}
-
+ /* Command needed to be synchronised with the 3D? */
if (psKick->h3DSyncInfo != IMG_NULL)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->h3DSyncInfo;
@@ -722,7 +778,7 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
#if defined(NO_HARDWARE)
-
+ /* Update sync objects pretending that we have done the job*/
for(i = 0; i < psKick->ui32NumSrcSync; i++)
{
psSyncInfo = (PVRSRV_KERNEL_SYNC_INFO *)psKick->ahSrcSyncInfo[i];
@@ -753,5 +809,5 @@ IMG_EXPORT PVRSRV_ERROR SGXSubmit2DKM(IMG_HANDLE hDevHandle, PVRSRV_2D_SGX_KICK
return eError;
}
-#endif
-#endif
+#endif /* SGX_FEATURE_2D_HARDWARE */
+#endif /* TRANSFER_QUEUE */
diff --git a/sgx/services4/srvkm/devices/sgx/sgxutils.c b/sgx/services4/srvkm/devices/sgx/sgxutils.c
index 1fbca00..b64f545 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxutils.c
+++ b/sgx/services4/srvkm/devices/sgx/sgxutils.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific utility routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device specific functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <stddef.h>
@@ -43,12 +60,14 @@
#include "ttrace.h"
#ifdef __linux__
-#include <linux/kernel.h>
-#include <linux/string.h>
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
#else
#include <stdio.h>
#endif
+IMG_UINT64 ui64KickCount;
+
#if defined(SYS_CUSTOM_POWERDOWN)
PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32CallerID);
@@ -56,20 +75,38 @@ PVRSRV_ERROR SysPowerDownMISR(PVRSRV_DEVICE_NODE * psDeviceNode, IMG_UINT32 ui32
+/*!
+******************************************************************************
+
+ @Function SGXPostActivePowerEvent
+
+ @Description
+
+ post power event functionality (e.g. restart)
+
+ @Input psDeviceNode : SGX Device Node
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+
+ @Return IMG_VOID :
+
+******************************************************************************/
static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
IMG_UINT32 ui32CallerID)
{
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
-
+ /* Update the counter for stats. */
psSGXHostCtl->ui32NumActivePowerEvents++;
if ((psSGXHostCtl->ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_POWEROFF_RESTART_IMMEDIATE) != 0)
{
+ PVR_DPF((PVR_DBG_MESSAGE, "SGXPostActivePowerEvent: SGX requests immediate restart"));
-
-
+ /*
+ Events were queued during the active power
+ request, so SGX will need to be restarted.
+ */
if (ui32CallerID == ISR_ID)
{
psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
@@ -82,6 +119,22 @@ static IMG_VOID SGXPostActivePowerEvent(PVRSRV_DEVICE_NODE * psDeviceNode,
}
+/*!
+******************************************************************************
+
+ @Function SGXTestActivePowerEvent
+
+ @Description
+
+ Checks whether the microkernel has generated an active power event. If so,
+ perform the power transition.
+
+ @Input psDeviceNode : SGX Device Node
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+
+ @Return IMG_VOID :
+
+******************************************************************************/
IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_UINT32 ui32CallerID)
{
@@ -89,38 +142,76 @@ IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
- if (((psSGXHostCtl->ui32InterruptFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) != 0) &&
- ((psSGXHostCtl->ui32InterruptClearFlags & PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER) == 0))
+#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 /* SYS_SUPPORTS_SGX_IDLE_CALLBACK */
+
+ /*
+ * 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;
+ }
+ else 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;
+ }
+
+ /* Microkernel is idle and is requesting to be powered down. */
psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
-
+ /* Suspend pdumping. */
PDUMPSUSPEND();
#if defined(SYS_CUSTOM_POWERDOWN)
-
-
-
+ /*
+ Some power down code cannot be executed inside an MISR on
+ some platforms that use mutexes inside the power code.
+ */
eError = SysPowerDownMISR(psDeviceNode, ui32CallerID);
#else
eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE_OFF,
- ui32CallerID, IMG_FALSE);
+ PVRSRV_DEV_POWER_STATE_OFF);
if (eError == PVRSRV_OK)
{
SGXPostActivePowerEvent(psDeviceNode, ui32CallerID);
}
#endif
- if (eError == PVRSRV_ERROR_RETRY)
- {
-
-
- psSGXHostCtl->ui32InterruptClearFlags &= ~PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
- eError = PVRSRV_OK;
- }
+ PVRSRVPowerUnlock(ui32CallerID);
-
+ /* Resume pdumping */
PDUMPRESUME();
}
@@ -131,6 +222,15 @@ IMG_VOID SGXTestActivePowerEvent (PVRSRV_DEVICE_NODE *psDeviceNode,
}
+/******************************************************************************
+ FUNCTION : SGXAcquireKernelCCBSlot
+
+ PURPOSE : Attempts to obtain a slot in the Kernel CCB
+
+ PARAMETERS : psCCB - the CCB
+
+ RETURNS : Address of space if available, IMG_NULL otherwise
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SGXAcquireKernelCCBSlot)
#endif
@@ -146,10 +246,27 @@ static INLINE SGXMKIF_COMMAND * SGXAcquireKernelCCBSlot(PVRSRV_SGX_CCB_INFO *psC
OSSleepms(1);
} END_LOOP_UNTIL_TIMEOUT();
-
+ /* Time out on waiting for CCB space */
return IMG_NULL;
}
+/*!
+******************************************************************************
+
+ @Function SGXScheduleCCBCommand
+
+ @Description - Submits a CCB command and kicks the ukernel (without
+ power management)
+
+ @Input psDevInfo - pointer to device info
+ @Input eCmdType - see SGXMKIF_CMD_*
+ @Input psCommandData - kernel CCB command
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+ @Input ui32PDumpFlags
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
SGXMKIF_CMD_TYPE eCmdType,
SGXMKIF_COMMAND *psCommandData,
@@ -162,6 +279,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
PVRSRV_ERROR eError = PVRSRV_OK;
SGXMKIF_COMMAND *psSGXCommand;
PVRSRV_SGXDEV_INFO *psDevInfo = psDeviceNode->pvDevice;
+ SGXMKIF_HOST_CTL *psSGXHostCtl = psDevInfo->psSGXHostCtl;
#if defined(FIX_HW_BRN_31620)
IMG_UINT32 ui32CacheMasks[4];
IMG_UINT32 i;
@@ -185,7 +303,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
psMMUContext = psDevInfo->hKernelMMUContext;
psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[0]);
-
+ /* Put the apps memory context in the bottom half */
if (hDevMemContext)
{
BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
@@ -194,7 +312,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
psDeviceNode->pfnMMUGetCacheFlushRange(psMMUContext, &ui32CacheMasks[2]);
}
-
+ /* If we have an outstanding flush request then set the cachecontrol bit */
if (ui32CacheMasks[0] || ui32CacheMasks[1] || ui32CacheMasks[2] || ui32CacheMasks[3])
{
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_BIF_PD;
@@ -202,10 +320,11 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
#endif
#if defined(FIX_HW_BRN_28889)
-
-
-
-
+ /*
+ If the data cache and bif cache need invalidating there has been a cleanup
+ request. Therefore, we need to send the invalidate seperately and wait
+ for it to complete.
+ */
if ( (eCmdType != SGXMKIF_CMD_PROCESS_QUEUES) &&
((psDevInfo->ui32CacheControl & SGXMKIF_CC_INVAL_DATA) != 0) &&
((psDevInfo->ui32CacheControl & (SGXMKIF_CC_INVAL_BIF_PT | SGXMKIF_CC_INVAL_BIF_PD)) != 0))
@@ -228,7 +347,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
goto Exit;
}
-
+ /* Wait for the invalidate to happen */
#if !defined(NO_HARDWARE)
if(PollForValueKM(&psSGXHostCtl->ui32InvalStatus,
PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE,
@@ -243,7 +362,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
#endif
#if defined(PDUMP)
-
+ /* Pdump the poll as well. */
PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for BIF cache invalidate request to complete");
PDUMPMEMPOL(psSGXHostCtlMemInfo,
offsetof(SGXMKIF_HOST_CTL, ui32InvalStatus),
@@ -252,7 +371,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
PDUMP_POLL_OPERATOR_EQUAL,
0,
MAKEUNIQUETAG(psSGXHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
psSGXHostCtl->ui32InvalStatus &= ~(PVRSRV_USSE_EDM_BIF_INVAL_COMPLETE);
PDUMPMEM(IMG_NULL, psSGXHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psSGXHostCtlMemInfo));
@@ -267,7 +386,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
SGXMKIF_COMMAND sPDECacheCommand = {0};
IMG_DEV_PHYADDR sDevPAddr;
-
+ /* Put the kernel info in the top 1/2 of the data */
psMMUContext = psDevInfo->hKernelMMUContext;
psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
@@ -275,7 +394,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
sPDECacheCommand.ui32Data[1] = ui32CacheMasks[0];
sPDECacheCommand.ui32Data[2] = ui32CacheMasks[1];
-
+ /* Put the apps memory context in the bottom half */
if (hDevMemContext)
{
BM_CONTEXT *psBMContext = (BM_CONTEXT *) hDevMemContext;
@@ -283,13 +402,13 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
psMMUContext = psBMContext->psMMUContext;
psDeviceNode->pfnMMUGetPDPhysAddr(psMMUContext, &sDevPAddr);
-
+ /* Or in 1 to the lsb to show we have a valid context */
sPDECacheCommand.ui32Data[3] = sDevPAddr.uiAddr | 1;
sPDECacheCommand.ui32Data[4] = ui32CacheMasks[2];
sPDECacheCommand.ui32Data[5] = ui32CacheMasks[3];
}
-
+ /* Only do a kick if there is any update */
if (sPDECacheCommand.ui32Data[1] | sPDECacheCommand.ui32Data[2] | sPDECacheCommand.ui32Data[4] |
sPDECacheCommand.ui32Data[5])
{
@@ -308,7 +427,11 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
}
#endif
#if defined(PDUMP)
-
+ /*
+ * For persistent processes, the HW kicks should not go into the
+ * extended init phase; only keep memory transactions from the
+ * window system which are necessary to run the client app.
+ */
{
PVRSRV_PER_PROCESS_DATA* psPerProc = PVRSRVFindPerProcessData();
if(psPerProc != IMG_NULL)
@@ -316,12 +439,12 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
bPersistentProcess = psPerProc->bPDumpPersistent;
}
}
-#endif
+#endif /* PDUMP */
psKernelCCB = psDevInfo->psKernelCCBInfo;
psSGXCommand = SGXAcquireKernelCCBSlot(psKernelCCB);
-
+ /* Wait for CCB space timed out */
if(!psSGXCommand)
{
PVR_DPF((PVR_DBG_ERROR, "SGXScheduleCCBCommand: Wait for CCB space timed out")) ;
@@ -329,18 +452,18 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
goto Exit;
}
-
+ /* embed cache control word */
psCommandData->ui32CacheControl = psDevInfo->ui32CacheControl;
#if defined(PDUMP)
-
+ /* Accumulate any cache invalidates that may have happened */
psDevInfo->sPDContext.ui32CacheControl |= psDevInfo->ui32CacheControl;
#endif
-
+ /* and clear it */
psDevInfo->ui32CacheControl = 0;
-
+ /* Copy command data over */
*psSGXCommand = *psCommandData;
if (eCmdType >= SGXMKIF_CMD_MAX)
@@ -350,11 +473,13 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
goto Exit;
}
- if ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene)
+ if (eCmdType == SGXMKIF_CMD_2D ||
+ eCmdType == SGXMKIF_CMD_TRANSFER ||
+ ((eCmdType == SGXMKIF_CMD_TA) && bLastInScene))
{
SYS_DATA *psSysData;
-
+ /* CPU cache clean control */
SysAcquireData(&psSysData);
if(psSysData->ePendingCacheOpType == PVRSRV_MISC_INFO_CPUCACHEOP_FLUSH)
@@ -366,18 +491,18 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
OSCleanCPUCacheKM();
}
-
+ /* Clear the pending op */
psSysData->ePendingCacheOpType = PVRSRV_MISC_INFO_CPUCACHEOP_NONE;
}
PVR_ASSERT(eCmdType < SGXMKIF_CMD_MAX);
- psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType];
+ psSGXCommand->ui32ServiceAddress = psDevInfo->aui32HostKickAddr[eCmdType]; /* PRQA S 3689 */ /* misuse of enums for bounds checking */
#if defined(PDUMP)
if ((ui32CallerID != ISR_ID) && (bPDumpIsSuspended == IMG_FALSE) &&
(bPersistentProcess == IMG_FALSE) )
{
-
+ /* Poll for space in the CCB. */
PDUMPCOMMENTWITHFLAGS(ui32PDumpFlags, "Poll for space in the Kernel CCB\r\n");
PDUMPMEMPOL(psKernelCCB->psCCBCtlMemInfo,
offsetof(PVRSRV_SGX_CCB_CTL, ui32ReadOffset),
@@ -397,7 +522,7 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
ui32PDumpFlags,
MAKEUNIQUETAG(psKernelCCB->psCCBMemInfo));
-
+ /* Overwrite cache control with pdump shadow */
PDUMPMEM(&psDevInfo->sPDContext.ui32CacheControl,
psKernelCCB->psCCBMemInfo,
psKernelCCB->ui32CCBDumpWOff * sizeof(SGXMKIF_COMMAND) +
@@ -409,14 +534,14 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
if (PDumpIsCaptureFrameKM()
|| ((ui32PDumpFlags & PDUMP_FLAGS_CONTINUOUS) != 0))
{
-
+ /* Clear cache invalidate shadow */
psDevInfo->sPDContext.ui32CacheControl = 0;
}
}
#endif
#if defined(FIX_HW_BRN_26620) && defined(SGX_FEATURE_SYSTEM_CACHE) && !defined(SGX_BYPASS_SYSTEM_CACHE)
-
+ /* Make sure the previous command has been read before send the next one */
eError = PollForValueKM (psKernelCCB->pui32ReadOffset,
*psKernelCCB->pui32WriteOffset,
0xFF,
@@ -431,8 +556,9 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
}
#endif
-
-
+ /*
+ Increment the write offset
+ */
*psKernelCCB->pui32WriteOffset = (*psKernelCCB->pui32WriteOffset + 1) & 255;
#if defined(PDUMP)
@@ -482,9 +608,16 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
*psDevInfo->pui32KernelCCBEventKicker = (*psDevInfo->pui32KernelCCBEventKicker + 1) & 0xFF;
+ /*
+ * New command submission is considered a proper handling of any pending APM
+ * event, so mark it as handled to prevent other host threads from taking
+ * action.
+ */
+ psSGXHostCtl->ui32InterruptClearFlags |= PVRSRV_USSE_EDM_INTERRUPT_ACTIVE_POWER;
+
OSWriteMemoryBarrier();
-
+ /* Order is importent for post processor! */
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
MKSYNC_TOKEN_KERNEL_CCB_OFFSET, *psKernelCCB->pui32WriteOffset);
PVR_TTRACE_UI32(PVRSRV_TRACE_GROUP_MKSYNC, PVRSRV_TRACE_CLASS_NONE,
@@ -506,15 +639,32 @@ PVRSRV_ERROR SGXScheduleCCBCommand(PVRSRV_DEVICE_NODE *psDeviceNode,
OSMemoryBarrier();
#if defined(NO_HARDWARE)
-
+ /* Increment read offset */
*psKernelCCB->pui32ReadOffset = (*psKernelCCB->pui32ReadOffset + 1) & 255;
#endif
+ ui64KickCount++;
Exit:
return eError;
}
+/*!
+******************************************************************************
+
+ @Function SGXScheduleCCBCommandKM
+
+ @Description - Submits a CCB command and kicks the ukernel
+
+ @Input psDeviceNode - pointer to SGX device node
+ @Input eCmdType - see SGXMKIF_CMD_*
+ @Input psCommandData - kernel CCB command
+ @Input ui32CallerID - KERNEL_ID or ISR_ID
+ @Input ui32PDumpFlags
+
+ @Return ui32Error - success or failure
+
+******************************************************************************/
PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
SGXMKIF_CMD_TYPE eCmdType,
SGXMKIF_COMMAND *psCommandData,
@@ -523,16 +673,47 @@ PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_HANDLE hDevMemContext,
IMG_BOOL bLastInScene)
{
- PVRSRV_ERROR eError;
+ PVRSRV_ERROR eError;
-
+ eError = PVRSRVPowerLock(ui32CallerID, IMG_FALSE);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (ui32CallerID == ISR_ID)
+ {
+ SYS_DATA *psSysData;
+
+ /*
+ ISR failed to acquire lock so it must be held by a kernel thread.
+ Bring up and kick SGX if necessary when the lock is available.
+ */
+ psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
+ eError = PVRSRV_OK;
+
+ SysAcquireData(&psSysData);
+ OSScheduleMISR(psSysData);
+ }
+ else
+ {
+ /*
+ Return to srvclient for retry.
+ */
+ }
+
+ return eError;
+ }
+ else if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
+ return eError;
+ }
+
+ /* Note that a power-up has been dumped in the init phase. */
PDUMPSUSPEND();
-
+ /* Ensure that SGX is powered up before kicking the ukernel. */
eError = PVRSRVSetDevicePowerStateKM(psDeviceNode->sDevId.ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE_ON,
- ui32CallerID,
- IMG_TRUE);
+ PVRSRV_DEV_POWER_STATE_ON);
PDUMPRESUME();
@@ -542,33 +723,8 @@ PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
}
else
{
- if (eError == PVRSRV_ERROR_RETRY)
- {
- if (ui32CallerID == ISR_ID)
- {
- SYS_DATA *psSysData;
-
-
-
-
- psDeviceNode->bReProcessDeviceCommandComplete = IMG_TRUE;
- eError = PVRSRV_OK;
-
- SysAcquireData(&psSysData);
- OSScheduleMISR(psSysData);
- }
- else
- {
-
-
- }
- }
- else
- {
- PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
- "ui32CallerID:%d eError:%u", ui32CallerID, eError));
- }
-
+ PVR_DPF((PVR_DBG_ERROR,"SGXScheduleCCBCommandKM failed to acquire lock - "
+ "ui32CallerID:%d eError:%u", ui32CallerID, eError));
return eError;
}
@@ -579,6 +735,16 @@ PVRSRV_ERROR SGXScheduleCCBCommandKM(PVRSRV_DEVICE_NODE *psDeviceNode,
}
+/*!
+******************************************************************************
+
+ @Function SGXScheduleProcessQueuesKM
+
+ @Description - Software command complete handler
+
+ @Input psDeviceNode - SGX device node
+
+******************************************************************************/
PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
{
PVRSRV_ERROR eError;
@@ -590,7 +756,7 @@ PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
ui32PowerStatus = psHostCtl->ui32PowerStatus;
if ((ui32PowerStatus & PVRSRV_USSE_EDM_POWMAN_NO_WORK) != 0)
{
-
+ /* The ukernel has no work to do so don't waste power. */
return PVRSRV_OK;
}
@@ -605,11 +771,41 @@ PVRSRV_ERROR SGXScheduleProcessQueuesKM(PVRSRV_DEVICE_NODE *psDeviceNode)
}
+/*!
+******************************************************************************
+
+ @Function SGXIsDevicePowered
+
+ @Description
+
+ Whether the device is powered, for the purposes of lockup detection.
+
+ @Input psDeviceNode - pointer to device node
+
+ @Return IMG_BOOL : Whether device is powered
+
+******************************************************************************/
IMG_BOOL SGXIsDevicePowered(PVRSRV_DEVICE_NODE *psDeviceNode)
{
return PVRSRVIsDevicePowered(psDeviceNode->sDevId.ui32DeviceIndex);
}
+/*!
+*******************************************************************************
+
+ @Function SGXGetInternalDevInfoKM
+
+ @Description
+ Gets device information that is not intended to be passed
+ on beyond the srvclient libs.
+
+ @Input hDevCookie
+
+ @Output psSGXInternalDevInfo
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
#if defined (SUPPORT_SID_INTERFACE)
@@ -623,7 +819,7 @@ PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
psSGXInternalDevInfo->ui32Flags = psDevInfo->ui32Flags;
psSGXInternalDevInfo->bForcePTOff = (IMG_BOOL)psDevInfo->bForcePTOff;
-
+ /* This should be patched up by OS bridge code */
psSGXInternalDevInfo->hHostCtlKernelMemInfoHandle =
(IMG_HANDLE)psDevInfo->psKernelSGXHostCtlMemInfo;
@@ -631,6 +827,19 @@ PVRSRV_ERROR SGXGetInternalDevInfoKM(IMG_HANDLE hDevCookie,
}
+/*****************************************************************************
+ FUNCTION : SGXCleanupRequest
+
+ PURPOSE : Wait for the microkernel to clean up its references to either a
+ render context or render target.
+
+ PARAMETERS : psDeviceNode - SGX device node
+ psHWDataDevVAddr - Device Address of the resource
+ ui32CleanupType - PVRSRV_CLEANUPCMD_*
+ bForceCleanup - Skips sync polling
+
+ RETURNS : error status
+*****************************************************************************/
PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_VIRTADDR *psHWDataDevVAddr,
IMG_UINT32 ui32CleanupType,
@@ -654,11 +863,12 @@ PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
if (eError != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Failed to submit clean-up command"));
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
return eError;
}
-
+ /* Wait for the uKernel process the cleanup request */
#if !defined(NO_HARDWARE)
if(PollForValueKM(&psHostCtl->ui32CleanupStatus,
PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
@@ -669,38 +879,59 @@ PVRSRV_ERROR SGXCleanupRequest(PVRSRV_DEVICE_NODE *psDeviceNode,
{
PVR_DPF((PVR_DBG_ERROR,"SGXCleanupRequest: Wait for uKernel to clean up (%u) failed", ui32CleanupType));
eError = PVRSRV_ERROR_TIMEOUT;
+ SGXDumpDebugInfo(psDevInfo, IMG_FALSE);
PVR_DBG_BREAK;
}
#endif
#if defined(PDUMP)
-
+ /*
+ Pdump the poll as well.
+ Note:
+ We don't expect the cleanup to report busy as the client should have
+ ensured the the resource has been finished with before requesting
+ it's cleanup. This isn't true of the abnormal termination case but
+ we don't expect to PDump that. Unless/until PDump has flow control
+ there isn't anything else we can do.
+ */
PDUMPCOMMENTWITHFLAGS(0, "Host Control - Poll for clean-up request to complete");
PDUMPMEMPOL(psHostCtlMemInfo,
offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus),
- PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
- PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
+ PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE,
PDUMP_POLL_OPERATOR_EQUAL,
0,
MAKEUNIQUETAG(psHostCtlMemInfo));
- #endif
+ #endif /* PDUMP */
if (eError != PVRSRV_OK)
{
return eError;
}
}
+
+ if (psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_BUSY)
+ {
+ /* Only one flag should be set */
+ PVR_ASSERT((psHostCtl->ui32CleanupStatus & PVRSRV_USSE_EDM_CLEANUPCMD_DONE) == 0);
+ eError = PVRSRV_ERROR_RETRY;
+ psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_BUSY);
+ }
+ else
+ {
+ eError = PVRSRV_OK;
+ psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE | PVRSRV_USSE_EDM_CLEANUPCMD_DONE);
+ }
- psHostCtl->ui32CleanupStatus &= ~(PVRSRV_USSE_EDM_CLEANUPCMD_COMPLETE);
PDUMPMEM(IMG_NULL, psHostCtlMemInfo, offsetof(SGXMKIF_HOST_CTL, ui32CleanupStatus), sizeof(IMG_UINT32), 0, MAKEUNIQUETAG(psHostCtlMemInfo));
-
+ /* Request the cache invalidate */
#if defined(SGX_FEATURE_SYSTEM_CACHE)
psDevInfo->ui32CacheControl |= (SGXMKIF_CC_INVAL_BIF_SL | SGXMKIF_CC_INVAL_DATA);
#else
psDevInfo->ui32CacheControl |= SGXMKIF_CC_INVAL_DATA;
#endif
- return PVRSRV_OK;
+ return eError;
}
@@ -710,6 +941,8 @@ typedef struct _SGX_HW_RENDER_CONTEXT_CLEANUP_
PVRSRV_KERNEL_MEM_INFO *psHWRenderContextMemInfo;
IMG_HANDLE hBlockAlloc;
PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
} SGX_HW_RENDER_CONTEXT_CLEANUP;
@@ -727,16 +960,44 @@ static PVRSRV_ERROR SGXCleanupHWRenderContextCallback(IMG_PVOID pvParam,
PVRSRV_CLEANUPCMD_RC,
bForceCleanup);
-
- PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
- psCleanup->psHWRenderContextMemInfo);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
- psCleanup,
- psCleanup->hBlockAlloc);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the Device Mem allocated */
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHWRenderContextMemInfo);
+ /* Finally, free the cleanup structure itself */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+ /*not nulling pointer, copy on stack*/
+ }
return eError;
}
@@ -747,6 +1008,8 @@ typedef struct _SGX_HW_TRANSFER_CONTEXT_CLEANUP_
PVRSRV_KERNEL_MEM_INFO *psHWTransferContextMemInfo;
IMG_HANDLE hBlockAlloc;
PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
} SGX_HW_TRANSFER_CONTEXT_CLEANUP;
@@ -764,16 +1027,44 @@ static PVRSRV_ERROR SGXCleanupHWTransferContextCallback(IMG_PVOID pvParam,
PVRSRV_CLEANUPCMD_TC,
bForceCleanup);
-
- PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
- psCleanup->psHWTransferContextMemInfo);
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
- psCleanup,
- psCleanup->hBlockAlloc);
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the Device Mem allocated */
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHWTransferContextMemInfo);
+ /* Finally, free the cleanup structure itself */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+ /*not nulling pointer, copy on stack*/
+ }
return eError;
}
@@ -824,6 +1115,9 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
| PVRSRV_MEM_CACHE_CONSISTENT,
ui32HWRenderContextSize,
32,
+ IMG_NULL,
+ 0,
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psCleanup->psHWRenderContextMemInfo,
"HW Render Context");
@@ -844,10 +1138,10 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
goto exit2;
}
-
+ /* Pass the DevVAddr of the new context back up through the bridge */
psHWRenderContextDevVAddr->uiAddr = psCleanup->psHWRenderContextMemInfo->sDevVAddr.uiAddr;
-
+ /* Retrieve the PDDevPAddr */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
hDevMemContext,
@@ -862,11 +1156,12 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
-
-
-
-
-
+ /*
+ patch-in the Page-Directory Device-Physical address. Note that this is
+ copied-in one byte at a time, as we have no guarantee that the usermode-
+ provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+ current CPU architecture.
+ */
pSrc = (IMG_UINT8 *)&sPDDevPAddr;
pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetToPDDevPAddr;
@@ -877,7 +1172,7 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
}
#if defined(PDUMP)
-
+ /* PDUMP the HW context */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Render context struct");
PDUMPMEM(
@@ -888,7 +1183,7 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psCleanup->psHWRenderContextMemInfo));
-
+ /* PDUMP the PDDevPAddr */
PDUMPCOMMENT("Page directory address in HW render context");
PDUMPPDDEVPADDR(
psCleanup->psHWRenderContextMemInfo,
@@ -900,6 +1195,7 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
psCleanup->hBlockAlloc = hBlockAlloc;
psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_HW_RENDER_CONTEXT,
@@ -917,6 +1213,7 @@ IMG_HANDLE SGXRegisterHWRenderContextKM(IMG_HANDLE hDeviceNode,
return (IMG_HANDLE)psCleanup;
+/* Error exit paths */
exit2:
PVRSRVFreeDeviceMemKM(hDeviceNode,
psCleanup->psHWRenderContextMemInfo);
@@ -925,7 +1222,7 @@ exit1:
sizeof(SGX_HW_RENDER_CONTEXT_CLEANUP),
psCleanup,
psCleanup->hBlockAlloc);
-
+ /*not nulling pointer, out of scope*/
exit0:
return IMG_NULL;
}
@@ -998,6 +1295,9 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
| PVRSRV_MEM_CACHE_CONSISTENT,
ui32HWTransferContextSize,
32,
+ IMG_NULL,
+ 0,
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psCleanup->psHWTransferContextMemInfo,
"HW Render Context");
@@ -1018,10 +1318,10 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
goto exit2;
}
-
+ /* Pass the DevVAddr of the new context back up through the bridge */
psHWTransferContextDevVAddr->uiAddr = psCleanup->psHWTransferContextMemInfo->sDevVAddr.uiAddr;
-
+ /* Retrieve the PDDevPAddr */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
hDevMemContext,
@@ -1036,11 +1336,12 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
-
-
-
-
-
+ /*
+ patch-in the Page-Directory Device-Physical address. Note that this is
+ copied-in one byte at a time, as we have no guarantee that the usermode-
+ provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+ current CPU architecture.
+ */
pSrc = (IMG_UINT8 *)&sPDDevPAddr;
pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetToPDDevPAddr;
@@ -1051,7 +1352,7 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
}
#if defined(PDUMP)
-
+ /* PDUMP the HW Transfer Context */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW Transfer context struct");
PDUMPMEM(
@@ -1062,7 +1363,7 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psCleanup->psHWTransferContextMemInfo));
-
+ /* PDUMP the PDDevPAddr */
PDUMPCOMMENT("Page directory address in HW transfer context");
PDUMPPDDEVPADDR(
@@ -1075,6 +1376,7 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
psCleanup->hBlockAlloc = hBlockAlloc;
psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_HW_TRANSFER_CONTEXT,
@@ -1092,6 +1394,7 @@ IMG_HANDLE SGXRegisterHWTransferContextKM(IMG_HANDLE hDeviceNode,
return (IMG_HANDLE)psCleanup;
+/* Error exit paths */
exit2:
PVRSRVFreeDeviceMemKM(hDeviceNode,
psCleanup->psHWTransferContextMemInfo);
@@ -1100,7 +1403,7 @@ exit1:
sizeof(SGX_HW_TRANSFER_CONTEXT_CLEANUP),
psCleanup,
psCleanup->hBlockAlloc);
-
+ /*not nulling pointer, out of scope*/
exit0:
return IMG_NULL;
@@ -1154,9 +1457,10 @@ PVRSRV_ERROR SGXSetTransferContextPriorityKM(
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
-
+ /*
+ cannot be sure that offset (passed from user-land) is safe to deref
+ as a word-ptr on current CPU arch: copy one byte at a time.
+ */
pDst = (IMG_UINT8 *)psCleanup->psHWTransferContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetOfPriorityField;
pSrc = (IMG_UINT8 *)&ui32Priority;
@@ -1195,9 +1499,10 @@ PVRSRV_ERROR SGXSetRenderContextPriorityKM(
return PVRSRV_ERROR_INVALID_PARAMS;
}
-
-
-
+ /*
+ cannot be sure that offset (passed from user-land) is safe to deref
+ as a word-ptr on current CPU arch: copy one byte at a time.
+ */
pDst = (IMG_UINT8 *)psCleanup->psHWRenderContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetOfPriorityField;
@@ -1218,6 +1523,8 @@ typedef struct _SGX_HW_2D_CONTEXT_CLEANUP_
PVRSRV_KERNEL_MEM_INFO *psHW2DContextMemInfo;
IMG_HANDLE hBlockAlloc;
PRESMAN_ITEM psResItem;
+ IMG_BOOL bCleanupTimerRunning;
+ IMG_PVOID pvTimeData;
} SGX_HW_2D_CONTEXT_CLEANUP;
static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam,
@@ -1229,23 +1536,50 @@ static PVRSRV_ERROR SGXCleanupHW2DContextCallback(IMG_PVOID pvParam,
PVR_UNREFERENCED_PARAMETER(ui32Param);
-
+ /* First, ensure the context is no longer being utilised */
eError = SGXCleanupRequest(psCleanup->psDeviceNode,
&psCleanup->psHW2DContextMemInfo->sDevVAddr,
PVRSRV_CLEANUPCMD_2DC,
bForceCleanup);
-
- PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
- psCleanup->psHW2DContextMemInfo);
-
-
- OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
- sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
- psCleanup,
- psCleanup->hBlockAlloc);
-
+ if (eError == PVRSRV_ERROR_RETRY)
+ {
+ if (!psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeCreateWithUSOffset(&psCleanup->pvTimeData, MAX_CLEANUP_TIME_US);
+ psCleanup->bCleanupTimerRunning = IMG_TRUE;
+ }
+ else
+ {
+ if (OSTimeHasTimePassed(psCleanup->pvTimeData))
+ {
+ eError = PVRSRV_ERROR_TIMEOUT_POLLING_FOR_VALUE;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ }
+ else
+ {
+ if (psCleanup->bCleanupTimerRunning)
+ {
+ OSTimeDestroy(psCleanup->pvTimeData);
+ }
+ }
+ if (eError != PVRSRV_ERROR_RETRY)
+ {
+ /* Free the Device Mem allocated */
+ PVRSRVFreeDeviceMemKM(psCleanup->psDeviceNode,
+ psCleanup->psHW2DContextMemInfo);
+
+ /* Finally, free the cleanup structure itself */
+ OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP,
+ sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
+ psCleanup,
+ psCleanup->hBlockAlloc);
+ /*not nulling pointer, copy on stack*/
+ }
return eError;
}
@@ -1294,6 +1628,9 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
| PVRSRV_MEM_CACHE_CONSISTENT,
ui32HW2DContextSize,
32,
+ IMG_NULL,
+ 0,
+ 0,0,0,IMG_NULL, /* No sparse mapping data */
&psCleanup->psHW2DContextMemInfo,
"HW 2D Context");
@@ -1313,10 +1650,10 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
goto exit2;
}
-
+ /* Pass the DevVAddr of the new context back up through the bridge */
psHW2DContextDevVAddr->uiAddr = psCleanup->psHW2DContextMemInfo->sDevVAddr.uiAddr;
-
+ /* Retrieve the PDDevPAddr */
eError = PVRSRVLookupHandle(psPerProc->psHandleBase,
&hDevMemContextInt,
hDevMemContext,
@@ -1331,11 +1668,12 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
psMMUContext = BM_GetMMUContextFromMemContext(hDevMemContextInt);
sPDDevPAddr = psDeviceNode->pfnMMUGetPDDevPAddr(psMMUContext);
-
-
-
-
-
+ /*
+ patch-in the Page-Directory Device-Physical address. Note that this is
+ copied-in one byte at a time, as we have no guarantee that the usermode-
+ provided ui32OffsetToPDDevPAddr is a validly-aligned address for the
+ current CPU architecture.
+ */
pSrc = (IMG_UINT8 *)&sPDDevPAddr;
pDst = (IMG_UINT8 *)psCleanup->psHW2DContextMemInfo->pvLinAddrKM;
pDst += ui32OffsetToPDDevPAddr;
@@ -1346,7 +1684,7 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
}
#if defined(PDUMP)
-
+ /* PDUMP the HW 2D Context */
PDUMPCOMMENTWITHFLAGS(PDUMP_FLAGS_CONTINUOUS, "HW 2D context struct");
PDUMPMEM(
@@ -1357,7 +1695,7 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
PDUMP_FLAGS_CONTINUOUS,
MAKEUNIQUETAG(psCleanup->psHW2DContextMemInfo));
-
+ /* PDUMP the PDDevPAddr */
PDUMPCOMMENT("Page directory address in HW 2D transfer context");
PDUMPPDDEVPADDR(
psCleanup->psHW2DContextMemInfo,
@@ -1369,6 +1707,7 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
psCleanup->hBlockAlloc = hBlockAlloc;
psCleanup->psDeviceNode = psDeviceNode;
+ psCleanup->bCleanupTimerRunning = IMG_FALSE;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_HW_2D_CONTEXT,
@@ -1386,6 +1725,7 @@ IMG_HANDLE SGXRegisterHW2DContextKM(IMG_HANDLE hDeviceNode,
return (IMG_HANDLE)psCleanup;
+/* Error exit paths */
exit2:
PVRSRVFreeDeviceMemKM(hDeviceNode,
psCleanup->psHW2DContextMemInfo);
@@ -1394,7 +1734,7 @@ exit1:
sizeof(SGX_HW_2D_CONTEXT_CLEANUP),
psCleanup,
psCleanup->hBlockAlloc);
-
+ /*not nulling pointer, out of scope*/
exit0:
return IMG_NULL;
}
@@ -1418,8 +1758,16 @@ PVRSRV_ERROR SGXUnregisterHW2DContextKM(IMG_HANDLE hHW2DContext, IMG_BOOL bForce
return eError;
}
-#endif
+#endif /* #if defined(SGX_FEATURE_2D_HARDWARE)*/
+/*!****************************************************************************
+ @Function SGX2DQuerySyncOpsCompleteKM
+
+ @Input psSyncInfo : Sync object to be queried
+
+ @Return IMG_TRUE - ops complete, IMG_FALSE - ops pending
+
+******************************************************************************/
#ifdef INLINE_IS_PRAGMA
#pragma inline(SGX2DQuerySyncOpsComplete)
#endif
@@ -1436,6 +1784,16 @@ IMG_BOOL SGX2DQuerySyncOpsComplete(PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
);
}
+/*!****************************************************************************
+ @Function SGX2DQueryBlitsCompleteKM
+
+ @Input psDevInfo : SGX device info structure
+
+ @Input psSyncInfo : Sync object to be queried
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
IMG_EXPORT
PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
PVRSRV_KERNEL_SYNC_INFO *psSyncInfo,
@@ -1452,20 +1810,20 @@ PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
{
-
+ /* Instant success */
PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Blits complete."));
return PVRSRV_OK;
}
-
+ /* Not complete yet */
if (!bWaitForComplete)
{
-
+ /* Just report not complete */
PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: No wait. Ops pending."));
return PVRSRV_ERROR_CMD_NOT_PROCESSED;
}
-
+ /* Start polling */
PVR_DPF((PVR_DBG_MESSAGE, "SGX2DQueryBlitsCompleteKM: Ops pending. Start polling."));
LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
@@ -1474,7 +1832,7 @@ PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
if(SGX2DQuerySyncOpsComplete(psSyncInfo, ui32ReadOpsPending, ui32WriteOpsPending))
{
-
+ /* Success */
PVR_DPF((PVR_DBG_CALLTRACE, "SGX2DQueryBlitsCompleteKM: Wait over. Blits complete."));
return PVRSRV_OK;
}
@@ -1482,7 +1840,7 @@ PVRSRV_ERROR SGX2DQueryBlitsCompleteKM(PVRSRV_SGXDEV_INFO *psDevInfo,
OSSleepms(1);
} END_LOOP_UNTIL_TIMEOUT();
-
+ /* Timed out */
PVR_DPF((PVR_DBG_ERROR,"SGX2DQueryBlitsCompleteKM: Timed out. Ops pending."));
#if defined(DEBUG)
@@ -1533,54 +1891,21 @@ IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
ui32Clocksx16 = (IMG_UINT32)(ui64Clocks / 16);
return ui32Clocksx16;
-#endif
+#endif /* EUR_CR_TIMER */
}
IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32SGXClocks)
{
-
-
+ /*
+ Round up to the next microsecond.
+ */
OSWaitus(1 + (ui32SGXClocks * 1000000 / psDevInfo->ui32CoreClockSpeed));
}
-IMG_EXPORT
-PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
- IMG_UINT32 *pui32SGXCoreID)
-{
- PVRSRV_SGXDEV_INFO *psDevInfo = (PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
- SGX_MISC_INFO sMiscInfo;
- PVRSRV_ERROR eError;
-
- sMiscInfo.eRequest = SGX_MISC_INFO_REQUEST_SGXREV;
- eError = SGXGetMiscInfoKM(psDevInfo, &sMiscInfo, psDeviceNode, NULL);
-
- *pui32SGXCoreRev = sMiscInfo.uData.sSGXFeatures.ui32CoreRev;
- *pui32SGXCoreID = sMiscInfo.uData.sSGXFeatures.ui32CoreID;
- return eError;
-}
-
-
-PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE *psDeviceNode,
- IMG_DEV_VIRTADDR *psHWContextDevVAddr,
- IMG_BOOL bResume)
-{
- PVRSRV_ERROR eError;
- SGXMKIF_COMMAND sCommand = {0};
-
- sCommand.ui32Data[0] = psHWContextDevVAddr->uiAddr;
- sCommand.ui32Data[1] = bResume ? PVRSRV_CTXSUSPCMD_RESUME : PVRSRV_CTXSUSPCMD_SUSPEND;
-
- eError = SGXScheduleCCBCommandKM(psDeviceNode, SGXMKIF_CMD_CONTEXTSUSPEND, &sCommand, KERNEL_ID, 0, IMG_NULL, IMG_FALSE);
- if (eError != PVRSRV_OK)
- {
- PVR_DPF((PVR_DBG_ERROR,"SGXContextSuspend: Failed to submit context suspend command"));
- return eError;
- }
-
- return eError;
-}
-
+/******************************************************************************
+ End of file (sgxutils.c)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/devices/sgx/sgxutils.h b/sgx/services4/srvkm/devices/sgx/sgxutils.h
index ae6dbc7..d21ad02 100644
--- a/sgx/services4/srvkm/devices/sgx/sgxutils.h
+++ b/sgx/services4/srvkm/devices/sgx/sgxutils.h
@@ -1,33 +1,50 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Device specific utility routines declarations
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Inline functions/structures specific to SGX
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "perproc.h"
#include "sgxinfokm.h"
-
+/* PRQA S 3410 7 */ /* macros require the absence of some brackets */
#define CCB_OFFSET_IS_VALID(type, psCCBMemInfo, psCCBKick, offset) \
((sizeof(type) <= (psCCBMemInfo)->uAllocSize) && \
((psCCBKick)->offset <= (psCCBMemInfo)->uAllocSize - sizeof(type)))
@@ -36,6 +53,8 @@
((type *)(((IMG_CHAR *)(psCCBMemInfo)->pvLinAddrKM) + \
(psCCBKick)->offset))
+extern IMG_UINT64 ui64KickCount;
+
IMG_IMPORT
IMG_VOID SGXTestActivePowerEvent(PVRSRV_DEVICE_NODE *psDeviceNode,
@@ -123,6 +142,21 @@ IMG_UINT32 SGXConvertTimeStamp(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32TimeWraps,
IMG_UINT32 ui32Time);
+/*!
+*******************************************************************************
+
+ @Function SGXWaitClocks
+
+ @Description
+
+ Wait for a specified number of SGX clock cycles to elapse.
+
+ @Input psDevInfo - SGX Device Info
+ @Input ui32SGXClocks - number of clock cycles to wait
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID SGXWaitClocks(PVRSRV_SGXDEV_INFO *psDevInfo,
IMG_UINT32 ui32SGXClocks);
@@ -135,7 +169,28 @@ IMG_IMPORT
PVRSRV_ERROR PVRSRVGetSGXRevDataKM(PVRSRV_DEVICE_NODE* psDeviceNode, IMG_UINT32 *pui32SGXCoreRev,
IMG_UINT32 *pui32SGXCoreID);
+/*!
+******************************************************************************
+
+ @Function SGXContextSuspend
+
+ @Description - Interface to the SGX microkernel to instruct it to suspend or
+ resume processing on a given context. This will interrupt current
+ processing of this context if a task is already running and is
+ interruptable.
+
+ @Input psDeviceNode SGX device node
+ @Input psHWContextDevVAddr SGX virtual address of the context to be suspended
+ or resumed. Can be of type SGXMKIF_HWRENDERCONTEXT,
+ SGXMKIF_HWTRANSFERCONTEXT or SGXMKIF_HW2DCONTEXT
+ @Input bResume IMG_TRUE to put a context into suspend state,
+ IMG_FALSE to resume a previously suspended context
+
+******************************************************************************/
PVRSRV_ERROR SGXContextSuspend(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_VIRTADDR *psHWContextDevVAddr,
IMG_BOOL bResume);
+/******************************************************************************
+ End of file (sgxutils.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/Kbuild.mk b/sgx/services4/srvkm/env/linux/Kbuild.mk
index 95df225..b101a5f 100755..100644
--- a/sgx/services4/srvkm/env/linux/Kbuild.mk
+++ b/sgx/services4/srvkm/env/linux/Kbuild.mk
@@ -1,26 +1,43 @@
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# 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.
+# The contents of this file are subject to the MIT license as set out below.
#
-# 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.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# 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 above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# 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
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
$(PVRSRV_MODNAME)-y += \
services4/srvkm/env/linux/osfunc.o \
@@ -40,22 +57,36 @@ $(PVRSRV_MODNAME)-y += \
services4/srvkm/common/deviceclass.o \
services4/srvkm/common/handle.o \
services4/srvkm/common/hash.o \
+ services4/srvkm/common/lists.o \
+ services4/srvkm/common/mem.o \
+ services4/srvkm/common/mem_debug.o \
services4/srvkm/common/metrics.o \
+ services4/srvkm/common/osfunc_common.o \
+ services4/srvkm/common/pdump_common.o \
+ services4/srvkm/common/perproc.o \
+ services4/srvkm/common/power.o \
services4/srvkm/common/pvrsrv.o \
services4/srvkm/common/queue.o \
services4/srvkm/common/ra.o \
+ services4/srvkm/common/refcount.o \
services4/srvkm/common/resman.o \
- services4/srvkm/common/power.o \
- services4/srvkm/common/mem.o \
- services4/srvkm/common/pdump_common.o \
services4/srvkm/bridged/bridged_support.o \
services4/srvkm/bridged/bridged_pvr_bridge.o \
- services4/srvkm/common/perproc.o \
services4/system/$(PVR_SYSTEM)/sysconfig.o \
- services4/system/$(PVR_SYSTEM)/sysutils.o \
- services4/srvkm/common/lists.o \
- services4/srvkm/common/mem_debug.o \
- services4/srvkm/common/osfunc_common.o
+ services4/system/$(PVR_SYSTEM)/sysutils.o
+
+$(PVRSRV_MODNAME)-$(CONFIG_ION_OMAP) += \
+ services4/srvkm/env/linux/ion.o
+
+ifeq ($(SUPPORT_ION),1)
+$(PVRSRV_MODNAME)-y += \
+ services4/srvkm/env/linux/ion.o
+endif
+
+ifeq ($(TTRACE),1)
+$(PVRSRV_MODNAME)-y += \
+ services4/srvkm/common/ttrace.o
+endif
ifneq ($(W),1)
CFLAGS_osfunc.o := -Werror
@@ -89,6 +120,7 @@ CFLAGS_perproc.o := -Werror
CFLAGS_lists.o := -Werror
CFLAGS_mem_debug.o := -Werror
CFLAGS_osfunc_common.o := -Werror
+CFLAGS_refcount.o := -Werror
endif
# SUPPORT_SGX==1 only
diff --git a/sgx/services4/srvkm/env/linux/Linux.mk b/sgx/services4/srvkm/env/linux/Linux.mk
index 0ea43aa..b5e9de4 100755..100644
--- a/sgx/services4/srvkm/env/linux/Linux.mk
+++ b/sgx/services4/srvkm/env/linux/Linux.mk
@@ -1,27 +1,43 @@
-#
-# Copyright (C) Imagination Technologies Ltd. All rights reserved.
+########################################################################### ###
+#@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+#@License Dual MIT/GPLv2
#
-# 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.
+# The contents of this file are subject to the MIT license as set out below.
#
-# 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.
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
#
-# 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 above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
#
-# 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
+# Alternatively, the contents of this file may be used under the terms of
+# the GNU General Public License Version 2 ("GPL") in which case the provisions
+# of GPL are applicable instead of those above.
#
-#
+# If you wish to allow use of your version of this file only under the terms of
+# GPL, and not to allow others to use your version of this file under the terms
+# of the MIT license, indicate your decision by deleting the provisions above
+# and replace them with the notice and other provisions required by GPL as set
+# out in the file called "GPL-COPYING" included in this distribution. If you do
+# not delete the provisions above, a recipient may use your version of this file
+# under the terms of either the MIT license or GPL.
+#
+# This License is also included in this distribution in the file called
+# "MIT-COPYING".
+#
+# EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+# PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+# PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+### ###########################################################################
modules := srvkm
diff --git a/sgx/services4/srvkm/env/linux/env_data.h b/sgx/services4/srvkm/env/linux/env_data.h
index 7716529..4a2b9b1 100644
--- a/sgx/services4/srvkm/env/linux/env_data.h
+++ b/sgx/services4/srvkm/env/linux/env_data.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Environmental Data header file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Linux-specific part of system data.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _ENV_DATA_
#define _ENV_DATA_
@@ -34,6 +50,11 @@
#include <linux/workqueue.h>
#endif
+/*
+ * Env data specific to linux - convenient place to put this
+ */
+
+/* Fairly arbitrary sizes - hopefully enough for all bridge calls */
#define PVRSRV_MAX_BRIDGE_IN_SIZE 0x1000
#define PVRSRV_MAX_BRIDGE_OUT_SIZE 0x1000
@@ -61,6 +82,13 @@ typedef struct _ENV_DATA_TAG
#else
struct tasklet_struct sMISRTasklet;
#endif
+#if defined (SUPPORT_ION)
+ IMG_HANDLE hIonHeaps;
+ IMG_HANDLE hIonDev;
+#endif
} ENV_DATA;
-#endif
+#endif /* _ENV_DATA_ */
+/*****************************************************************************
+ End of file (env_data.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/env_perproc.h b/sgx/services4/srvkm/env/linux/env_perproc.h
index 58e2c38..f434226 100644
--- a/sgx/services4/srvkm/env/linux/env_perproc.h
+++ b/sgx/services4/srvkm/env/linux/env_perproc.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OS specific per process data interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Linux per process data
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __ENV_PERPROC_H__
#define __ENV_PERPROC_H__
@@ -33,6 +49,7 @@
#include "services.h"
#include "handle.h"
+#define ION_CLIENT_NAME_SIZE 50
typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
{
IMG_HANDLE hBlockAlloc;
@@ -47,6 +64,10 @@ typedef struct _PVRSRV_ENV_PER_PROCESS_DATA_
struct drm_device *dev;
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
#endif
+#if defined (SUPPORT_ION)
+ struct ion_client *psIONClient;
+ IMG_CHAR azIonClientName[ION_CLIENT_NAME_SIZE];
+#endif
} PVRSRV_ENV_PER_PROCESS_DATA;
IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc);
@@ -59,5 +80,8 @@ PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
IMG_HANDLE LinuxTerminatingProcessPrivateData(IMG_VOID);
-#endif
+#endif /* __ENV_PERPROC_H__ */
+/******************************************************************************
+ End of file (env_perproc.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/event.c b/sgx/services4/srvkm/env/linux/event.c
index 7e160c3..1946e61 100644
--- a/sgx/services4/srvkm/env/linux/event.c
+++ b/sgx/services4/srvkm/env/linux/event.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Event Object
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -85,6 +101,20 @@ typedef struct PVRSRV_LINUX_EVENT_OBJECT_TAG
PVRSRV_LINUX_EVENT_OBJECT_LIST *psLinuxEventObjectList;
} PVRSRV_LINUX_EVENT_OBJECT;
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectListCreate
+
+ @Description
+
+ Linux wait object list creation
+
+ @Output hOSEventKM : Pointer to the event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
{
PVRSRV_LINUX_EVENT_OBJECT_LIST *psEventObjectList;
@@ -106,6 +136,20 @@ PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectListDestroy
+
+ @Description
+
+ Linux wait object list destruction
+
+ @Input hOSEventKM : Event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
{
@@ -126,13 +170,29 @@ PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList)
}
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT_LIST), psEventObjectList, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
}
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectDelete
+
+ @Description
+
+ Linux wait object removal
+
+ @Input hOSEventObjectList : Event object list handle
+ @Input hOSEventObject : Event object handle
+ @Input bResManCallback : Called from the resman
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hOSEventObject)
{
if(hOSEventObjectList)
@@ -155,6 +215,20 @@ PVRSRV_ERROR LinuxEventObjectDelete(IMG_HANDLE hOSEventObjectList, IMG_HANDLE hO
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectDeleteCallback
+
+ @Description
+
+ Linux wait object removal
+
+ @Input hOSEventObject : Event object handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup)
{
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject = pvParam;
@@ -173,10 +247,25 @@ static PVRSRV_ERROR LinuxEventObjectDeleteCallback(IMG_PVOID pvParam, IMG_UINT32
#endif
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT), psLinuxEventObject, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectAdd
+
+ @Description
+
+ Linux wait object addition
+
+ @Input hOSEventObjectList : Event object list handle
+ @Output phOSEventObject : Pointer to the event object handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOSEventObject)
{
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
@@ -192,7 +281,7 @@ PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOS
return PVRSRV_ERROR_OUT_OF_MEMORY;
}
-
+ /* allocate completion variable */
if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP, sizeof(PVRSRV_LINUX_EVENT_OBJECT),
(IMG_VOID **)&psLinuxEventObject, IMG_NULL,
"Linux Event Object") != PVRSRV_OK)
@@ -228,6 +317,20 @@ PVRSRV_ERROR LinuxEventObjectAdd(IMG_HANDLE hOSEventObjectList, IMG_HANDLE *phOS
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectSignal
+
+ @Description
+
+ Linux wait object signaling function
+
+ @Input hOSEventObjectList : Event object list handle
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
{
PVRSRV_LINUX_EVENT_OBJECT *psLinuxEventObject;
@@ -236,7 +339,10 @@ PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
psList = &psLinuxEventObjectList->sList;
-
+ /*
+ * We don't take the write lock in interrupt context, so we don't
+ * need to use read_lock_irqsave.
+ */
read_lock(&psLinuxEventObjectList->sLock);
list_for_each(psListEntry, psList)
{
@@ -252,6 +358,22 @@ PVRSRV_ERROR LinuxEventObjectSignal(IMG_HANDLE hOSEventObjectList)
}
+/*!
+******************************************************************************
+
+ @Function LinuxEventObjectWait
+
+ @Description
+
+ Linux wait object routine
+
+ @Input hOSEventObject : Event object handle
+
+ @Input ui32MSTimeout : Time out value in msec
+
+ @Return PVRSRV_ERROR : Error code
+
+******************************************************************************/
PVRSRV_ERROR LinuxEventObjectWait(IMG_HANDLE hOSEventObject, IMG_UINT32 ui32MSTimeout)
{
IMG_UINT32 ui32TimeStamp;
diff --git a/sgx/services4/srvkm/env/linux/event.h b/sgx/services4/srvkm/env/linux/event.h
index 3035283..88adb27 100644
--- a/sgx/services4/srvkm/env/linux/event.h
+++ b/sgx/services4/srvkm/env/linux/event.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Event Object
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
PVRSRV_ERROR LinuxEventObjectListCreate(IMG_HANDLE *phEventObjectList);
PVRSRV_ERROR LinuxEventObjectListDestroy(IMG_HANDLE hEventObjectList);
diff --git a/sgx/services4/srvkm/env/linux/linkage.h b/sgx/services4/srvkm/env/linux/linkage.h
index e64012c..94aae0b 100644
--- a/sgx/services4/srvkm/env/linux/linkage.h
+++ b/sgx/services4/srvkm/env/linux/linkage.h
@@ -1,29 +1,47 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux specific Services code internal interfaces
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Interfaces between various parts of the Linux specific
+ Services code, that don't have any other obvious
+ header file to go into.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __LINKAGE_H__
#define __LINKAGE_H__
@@ -45,8 +63,11 @@ IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT
void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el);
-#endif
+#endif /* PVR_MANUAL_POWER_CONTROL */
-#endif
+#endif /* DEBUG */
-#endif
+#endif /* __LINKAGE_H__ */
+/*****************************************************************************
+ End of file (linkage.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/lock.h b/sgx/services4/srvkm/env/linux/lock.h
index a0854c3..d6d5b50 100644
--- a/sgx/services4/srvkm/env/linux/lock.h
+++ b/sgx/services4/srvkm/env/linux/lock.h
@@ -1,32 +1,57 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Main driver lock
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description The main driver lock, held in most places in
+ the driver.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __LOCK_H__
#define __LOCK_H__
+/*
+ * Main driver lock, used to ensure driver code is single threaded.
+ * There are some places where this lock must not be taken, such as
+ * in the mmap related deriver entry points.
+ */
extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
-#endif
+#endif /* __LOCK_H__ */
+/*****************************************************************************
+ End of file (lock.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/mm.c b/sgx/services4/srvkm/env/linux/mm.c
index 3edbc49..dc2b471 100644
--- a/sgx/services4/srvkm/env/linux/mm.c
+++ b/sgx/services4/srvkm/env/linux/mm.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Misc memory management utility functions for Linux
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -32,6 +48,14 @@
#endif
#endif
+#if !defined(PVR_LINUX_MEM_AREA_POOL_MAX_PAGES)
+#define PVR_LINUX_MEM_AREA_POOL_MAX_PAGES 0
+#endif
+
+#include <linux/kernel.h>
+#include <asm/atomic.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <asm/io.h>
@@ -42,6 +66,12 @@
#include <linux/highmem.h>
#include <linux/sched.h>
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,1,0))
+#include <linux/shrinker.h>
+#endif
+#endif
+
#include "img_defs.h"
#include "services.h"
#include "servicesint.h"
@@ -60,6 +90,13 @@
#include "lists.h"
#endif
+/*
+ * The page pool entry count is an atomic int so that the shrinker function
+ * can return it even when we can't take the lock that protects the page pool
+ * list.
+ */
+static atomic_t g_sPagePoolEntryCount = ATOMIC_INIT(0);
+
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
typedef enum {
DEBUG_MEM_ALLOC_TYPE_KMALLOC,
@@ -68,13 +105,17 @@ typedef enum {
DEBUG_MEM_ALLOC_TYPE_IOREMAP,
DEBUG_MEM_ALLOC_TYPE_IO,
DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE,
+ DEBUG_MEM_ALLOC_TYPE_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ DEBUG_MEM_ALLOC_TYPE_VMAP,
+#endif
DEBUG_MEM_ALLOC_TYPE_COUNT
-}DEBUG_MEM_ALLOC_TYPE;
+} DEBUG_MEM_ALLOC_TYPE;
typedef struct _DEBUG_MEM_ALLOC_REC
{
DEBUG_MEM_ALLOC_TYPE eAllocType;
- IMG_VOID *pvKey;
+ IMG_VOID *pvKey; /* Some unique value (private to the eAllocType) */
IMG_VOID *pvCpuVAddr;
IMG_UINT32 ulCpuPAddr;
IMG_VOID *pvPrivateData;
@@ -85,7 +126,7 @@ typedef struct _DEBUG_MEM_ALLOC_REC
struct _DEBUG_MEM_ALLOC_REC *psNext;
struct _DEBUG_MEM_ALLOC_REC **ppsThis;
-}DEBUG_MEM_ALLOC_REC;
+} DEBUG_MEM_ALLOC_REC;
static IMPLEMENT_LIST_ANY_VA_2(DEBUG_MEM_ALLOC_REC, IMG_BOOL, IMG_FALSE)
static IMPLEMENT_LIST_ANY_VA(DEBUG_MEM_ALLOC_REC)
@@ -99,9 +140,17 @@ static DEBUG_MEM_ALLOC_REC *g_MemoryRecords;
static IMG_UINT32 g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
static IMG_UINT32 g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_COUNT];
-static IMG_UINT32 g_SysRAMWaterMark;
-static IMG_UINT32 g_SysRAMHighWaterMark;
+/* vmalloc + kmalloc + alloc_pages + kmem_cache */
+static IMG_UINT32 g_SysRAMWaterMark; /* Doesn't include page pool */
+static IMG_UINT32 g_SysRAMHighWaterMark; /* *DOES* include page pool */
+static inline IMG_UINT32
+SysRAMTrueWaterMark(void)
+{
+ return g_SysRAMWaterMark + PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount));
+}
+
+/* ioremap + io */
static IMG_UINT32 g_IOMemWaterMark;
static IMG_UINT32 g_IOMemHighWaterMark;
@@ -119,7 +168,7 @@ static IMG_VOID DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_V
static IMG_CHAR *DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType);
-static struct proc_dir_entry *g_SeqFileMemoryRecords =0;
+static struct proc_dir_entry *g_SeqFileMemoryRecords;
static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementMemoryRecords(struct seq_file * sfile, loff_t off);
@@ -153,7 +202,7 @@ static IMG_UINT32 g_LinuxMemAreaWaterMark;
static IMG_UINT32 g_LinuxMemAreaHighWaterMark;
-static struct proc_dir_entry *g_SeqFileMemArea=0;
+static struct proc_dir_entry *g_SeqFileMemArea;
static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off);
static void ProcSeqShowMemArea(struct seq_file *sfile,void* el);
@@ -169,8 +218,19 @@ static PVRSRV_LINUX_MUTEX g_sDebugMutex;
static void ProcSeqStartstopDebugMutex(struct seq_file *sfile,IMG_BOOL start);
#endif
-static LinuxKMemCache *psLinuxMemAreaCache;
+typedef struct
+{
+ /* Linkage for page pool LRU list */
+ struct list_head sPagePoolItem;
+
+ struct page *psPage;
+} LinuxPagePoolEntry;
+
+static LinuxKMemCache *g_PsLinuxMemAreaCache;
+static LinuxKMemCache *g_PsLinuxPagePoolCache;
+static LIST_HEAD(g_sPagePoolList);
+static int g_iPagePoolMaxEntries;
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
static IMG_VOID ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length);
@@ -185,165 +245,26 @@ static DEBUG_LINUX_MEM_AREA_REC *DebugLinuxMemAreaRecordFind(LinuxMemArea *psLin
static IMG_VOID DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea);
#endif
-PVRSRV_ERROR
-LinuxMMInit(IMG_VOID)
-{
-#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- LinuxInitMutex(&g_sDebugMutex);
-#endif
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
- {
- g_SeqFileMemArea = CreateProcReadEntrySeq(
- "mem_areas",
- NULL,
- ProcSeqNextMemArea,
- ProcSeqShowMemArea,
- ProcSeqOff2ElementMemArea,
- ProcSeqStartstopDebugMutex
- );
- if(!g_SeqFileMemArea)
- {
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- }
-#endif
-
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- {
- g_SeqFileMemoryRecords =CreateProcReadEntrySeq(
- "meminfo",
- NULL,
- ProcSeqNextMemoryRecords,
- ProcSeqShowMemoryRecords,
- ProcSeqOff2ElementMemoryRecords,
- ProcSeqStartstopDebugMutex
- );
- if(!g_SeqFileMemoryRecords)
- {
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
- }
-#endif
-
- psLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
- if(!psLinuxMemAreaCache)
- {
- PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate kmem_cache", __FUNCTION__));
- return PVRSRV_ERROR_OUT_OF_MEMORY;
- }
-
- return PVRSRV_OK;
-}
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
-static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
-{
- LinuxMemArea *psLinuxMemArea;
-
- psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
- __FUNCTION__,
- psCurrentRecord->psLinuxMemArea,
- LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
- psCurrentRecord->psLinuxMemArea->ui32ByteSize));
-
- LinuxMemAreaDeepFree(psLinuxMemArea);
-}
-#endif
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
-static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+static inline IMG_BOOL
+AreaIsUncached(IMG_UINT32 ui32AreaFlags)
{
-
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
- "type=%s "
- "CpuVAddr=%p "
- "CpuPAddr=0x%08x, "
- "allocated @ file=%s,line=%d",
- __FUNCTION__,
- DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
- psCurrentRecord->pvCpuVAddr,
- psCurrentRecord->ulCpuPAddr,
- psCurrentRecord->pszFileName,
- psCurrentRecord->ui32Line));
- switch(psCurrentRecord->eAllocType)
- {
- case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
- KFreeWrapper(psCurrentRecord->pvCpuVAddr);
- break;
- case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
- IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
- break;
- case DEBUG_MEM_ALLOC_TYPE_IO:
-
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
- break;
- case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
- VFreeWrapper(psCurrentRecord->pvCpuVAddr);
- break;
- case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
-
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
- break;
- case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
- KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
- break;
- default:
- PVR_ASSERT(0);
- }
+ return (ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED)) != 0;
}
-#endif
-
-IMG_VOID
-LinuxMMCleanup(IMG_VOID)
+static inline IMG_BOOL
+CanFreeToPool(LinuxMemArea *psLinuxMemArea)
{
-
-#if defined(DEBUG_LINUX_MEM_AREAS)
- {
- if(g_LinuxMemAreaCount)
- {
- PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
- __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
- }
-
- List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords,
- LinuxMMCleanup_MemAreas_ForEachCb);
-
- RemoveProcEntrySeq( g_SeqFileMemArea );
- }
-#endif
-
-
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- {
-
-
- List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords,
- LinuxMMCleanup_MemRecords_ForEachVa);
-
- RemoveProcEntrySeq( g_SeqFileMemoryRecords );
- }
-#endif
-
- if(psLinuxMemAreaCache)
- {
- KMemCacheDestroyWrapper(psLinuxMemAreaCache);
- psLinuxMemAreaCache=NULL;
- }
+ return AreaIsUncached(psLinuxMemArea->ui32AreaFlags) && !psLinuxMemArea->bNeedsCacheInvalidate;
}
-
IMG_VOID *
_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
IMG_VOID *pvRet;
pvRet = kmalloc(ui32ByteSize, uFlags);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- if(pvRet)
+ if (pvRet)
{
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_KMALLOC,
pvRet,
@@ -353,7 +274,7 @@ _KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *pszFileName, IM
ui32ByteSize,
pszFileName,
ui32Line
- );
+ );
}
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
@@ -406,27 +327,31 @@ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE eAllocType,
List_DEBUG_MEM_ALLOC_REC_Insert(&g_MemoryRecords, psRecord);
g_WaterMarkData[eAllocType] += ui32Bytes;
- if(g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
+ if (g_WaterMarkData[eAllocType] > g_HighWaterMarkData[eAllocType])
{
g_HighWaterMarkData[eAllocType] = g_WaterMarkData[eAllocType];
}
- if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
{
+ IMG_UINT32 ui32SysRAMTrueWaterMark;
+
g_SysRAMWaterMark += ui32Bytes;
- if(g_SysRAMWaterMark > g_SysRAMHighWaterMark)
+ ui32SysRAMTrueWaterMark = SysRAMTrueWaterMark();
+
+ if (ui32SysRAMTrueWaterMark > g_SysRAMHighWaterMark)
{
- g_SysRAMHighWaterMark = g_SysRAMWaterMark;
+ g_SysRAMHighWaterMark = ui32SysRAMTrueWaterMark;
}
}
- else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
{
g_IOMemWaterMark += ui32Bytes;
- if(g_IOMemWaterMark > g_IOMemHighWaterMark)
+ if (g_IOMemWaterMark > g_IOMemHighWaterMark)
{
g_IOMemHighWaterMark = g_IOMemWaterMark;
}
@@ -444,20 +369,20 @@ static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrent
eAllocType = va_arg(va, DEBUG_MEM_ALLOC_TYPE);
pvKey = va_arg(va, IMG_VOID*);
- if(psCurrentRecord->eAllocType == eAllocType
+ if (psCurrentRecord->eAllocType == eAllocType
&& psCurrentRecord->pvKey == pvKey)
{
eAllocType = psCurrentRecord->eAllocType;
g_WaterMarkData[eAllocType] -= psCurrentRecord->ui32Bytes;
- if(eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
+ if (eAllocType == DEBUG_MEM_ALLOC_TYPE_KMALLOC
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_VMALLOC
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
{
g_SysRAMWaterMark -= psCurrentRecord->ui32Bytes;
}
- else if(eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
+ else if (eAllocType == DEBUG_MEM_ALLOC_TYPE_IOREMAP
|| eAllocType == DEBUG_MEM_ALLOC_TYPE_IO)
{
g_IOMemWaterMark -= psCurrentRecord->ui32Bytes;
@@ -478,10 +403,12 @@ static IMG_BOOL DebugMemAllocRecordRemove_AnyVaCb(DEBUG_MEM_ALLOC_REC *psCurrent
static IMG_VOID
DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE eAllocType, IMG_VOID *pvKey, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
{
+/* DEBUG_MEM_ALLOC_REC **ppsCurrentRecord;*/
+
LinuxLockMutex(&g_sDebugMutex);
-
- if(!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
+ /* Locate the corresponding allocation entry */
+ if (!List_DEBUG_MEM_ALLOC_REC_IMG_BOOL_Any_va(g_MemoryRecords,
DebugMemAllocRecordRemove_AnyVaCb,
eAllocType,
pvKey))
@@ -504,27 +431,24 @@ DebugMemAllocRecordTypeToString(DEBUG_MEM_ALLOC_TYPE eAllocType)
"ALLOC_PAGES",
"IOREMAP",
"IO",
- "KMEM_CACHE_ALLOC"
+ "KMEM_CACHE_ALLOC",
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ "VMAP"
+#endif
};
return apszDebugMemoryRecordTypes[eAllocType];
}
#endif
-
-IMG_VOID *
-_VMallocWrapper(IMG_UINT32 ui32Bytes,
- IMG_UINT32 ui32AllocFlags,
- IMG_CHAR *pszFileName,
- IMG_UINT32 ui32Line)
+static IMG_BOOL
+AllocFlagsToPGProt(pgprot_t *pPGProtFlags, IMG_UINT32 ui32AllocFlags)
{
pgprot_t PGProtFlags;
- IMG_VOID *pvRet;
-
- switch(ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
+
+ switch (ui32AllocFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
case PVRSRV_HAP_CACHED:
- case PVRSRV_HAP_SMART:
PGProtFlags = PAGE_KERNEL;
break;
case PVRSRV_HAP_WRITECOMBINE:
@@ -535,17 +459,36 @@ _VMallocWrapper(IMG_UINT32 ui32Bytes,
break;
default:
PVR_DPF((PVR_DBG_ERROR,
- "VMAllocWrapper: unknown mapping flags=0x%08x",
- ui32AllocFlags));
+ "%s: Unknown mapping flags=0x%08x",
+ __FUNCTION__, ui32AllocFlags));
dump_stack();
+ return IMG_FALSE;
+ }
+
+ *pPGProtFlags = PGProtFlags;
+
+ return IMG_TRUE;
+}
+
+IMG_VOID *
+_VMallocWrapper(IMG_UINT32 ui32Bytes,
+ IMG_UINT32 ui32AllocFlags,
+ IMG_CHAR *pszFileName,
+ IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+ {
return NULL;
}
-
+ /* Allocate virtually contiguous pages */
pvRet = __vmalloc(ui32Bytes, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- if(pvRet)
+ if (pvRet)
{
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMALLOC,
pvRet,
@@ -555,7 +498,7 @@ _VMallocWrapper(IMG_UINT32 ui32Bytes,
PAGE_ALIGN(ui32Bytes),
pszFileName,
ui32Line
- );
+ );
}
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
@@ -579,31 +522,481 @@ _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
}
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+static IMG_VOID *
+_VMapWrapper(struct page **ppsPageList, IMG_UINT32 ui32NumPages, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+ pgprot_t PGProtFlags;
+ IMG_VOID *pvRet;
+
+ if (!AllocFlagsToPGProt(&PGProtFlags, ui32AllocFlags))
+ {
+ return NULL;
+ }
+
+ pvRet = vmap(ppsPageList, ui32NumPages, GFP_KERNEL | __GFP_HIGHMEM, PGProtFlags);
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ if (pvRet)
+ {
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_VMAP,
+ pvRet,
+ pvRet,
+ 0,
+ NULL,
+ PAGES_TO_BYTES(ui32NumPages),
+ pszFileName,
+ ui32Line
+ );
+ }
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ return pvRet;
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
+#else
+#define VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags) _VMapWrapper(ppsPageList, ui32Bytes, ui32AllocFlags, NULL, 0)
+#endif
+
+
+static IMG_VOID
+_VUnmapWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_VMAP, pvCpuVAddr, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+ vunmap(pvCpuVAddr);
+}
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, __FILE__, __LINE__)
+#else
+#define VUnmapWrapper(pvCpuVAddr) _VUnmapWrapper(pvCpuVAddr, NULL, 0)
+#endif
+
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
+
+
+IMG_VOID
+_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
+{
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
+#else
+ PVR_UNREFERENCED_PARAMETER(pszFileName);
+ PVR_UNREFERENCED_PARAMETER(ui32Line);
+#endif
+
+ kmem_cache_free(psCache, pvObject);
+}
+
+
+const IMG_CHAR *
+KMemCacheNameWrapper(LinuxKMemCache *psCache)
+{
+ PVR_UNREFERENCED_PARAMETER(psCache);
+
+ /* In this case kmem_cache_t is an incomplete typedef,
+ * so we can't even de-reference to get the name member. It is also a GPL export symbol */
+ return "";
+}
+
+
+static LinuxPagePoolEntry *
+LinuxPagePoolEntryAlloc(IMG_VOID)
+{
+ return KMemCacheAllocWrapper(g_PsLinuxPagePoolCache, GFP_KERNEL);
+}
+
+static IMG_VOID
+LinuxPagePoolEntryFree(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ KMemCacheFreeWrapper(g_PsLinuxPagePoolCache, psPagePoolEntry);
+}
+
+
+static struct page *
+AllocPageFromLinux(void)
+{
+ struct page *psPage;
+
+ psPage = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
+ if (!psPage)
+ {
+ return NULL;
+
+ }
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+ /* Reserve those pages to allow them to be re-mapped to user space */
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ SetPageReserved(psPage);
+#else
+ mem_map_reserve(psPage);
+#endif
+#endif
+ return psPage;
+}
+
+
+static IMG_VOID
+FreePageToLinux(struct page *psPage)
+{
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+ ClearPageReserved(psPage);
+#else
+ mem_map_reserve(psPage);
+#endif
+#endif
+ __free_pages(psPage, 0);
+}
+
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+static DEFINE_MUTEX(g_sPagePoolMutex);
+
+static inline void
+PagePoolLock(void)
+{
+ mutex_lock(&g_sPagePoolMutex);
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+ mutex_unlock(&g_sPagePoolMutex);
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+ return mutex_trylock(&g_sPagePoolMutex);
+}
+
+#else /* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */
+static inline void
+PagePoolLock(void)
+{
+}
+
+static inline void
+PagePoolUnlock(void)
+{
+}
+
+static inline int
+PagePoolTrylock(void)
+{
+ return 1;
+}
+#endif /* (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0) */
+
+
+static inline void
+AddEntryToPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_add_tail(&psPagePoolEntry->sPagePoolItem, &g_sPagePoolList);
+ atomic_inc(&g_sPagePoolEntryCount);
+}
+
+static inline void
+RemoveEntryFromPool(LinuxPagePoolEntry *psPagePoolEntry)
+{
+ list_del(&psPagePoolEntry->sPagePoolItem);
+ atomic_dec(&g_sPagePoolEntryCount);
+}
+
+static inline LinuxPagePoolEntry *
+RemoveFirstEntryFromPool(void)
+{
+ LinuxPagePoolEntry *psPagePoolEntry;
+
+ if (list_empty(&g_sPagePoolList))
+ {
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+ return NULL;
+ }
+
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) > 0);
+
+ psPagePoolEntry = list_first_entry(&g_sPagePoolList, LinuxPagePoolEntry, sPagePoolItem);
+
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ return psPagePoolEntry;
+}
+
+static struct page *
+AllocPage(IMG_UINT32 ui32AreaFlags, IMG_BOOL *pbFromPagePool)
+{
+ struct page *psPage = NULL;
+
+ /*
+ * Only uncached allocations can come from the page pool.
+ * The page pool is currently used to reduce the cost of
+ * invalidating the CPU cache when uncached memory is allocated.
+ */
+ if (AreaIsUncached(ui32AreaFlags) && atomic_read(&g_sPagePoolEntryCount) != 0)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry;
+
+ PagePoolLock();
+ psPagePoolEntry = RemoveFirstEntryFromPool();
+ PagePoolUnlock();
+
+ /* List may have changed since we checked the counter */
+ if (psPagePoolEntry)
+ {
+ psPage = psPagePoolEntry->psPage;
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+ *pbFromPagePool = IMG_TRUE;
+ }
+ }
+
+ if (!psPage)
+ {
+ psPage = AllocPageFromLinux();
+ if (psPage)
+ {
+ *pbFromPagePool = IMG_FALSE;
+ }
+ }
+
+ return psPage;
+
+}
+
+static IMG_VOID
+FreePage(IMG_BOOL bToPagePool, struct page *psPage)
+{
+ /* Only uncached allocations can be freed to the page pool */
+ if (bToPagePool && atomic_read(&g_sPagePoolEntryCount) < g_iPagePoolMaxEntries)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry = LinuxPagePoolEntryAlloc();
+ if (psPagePoolEntry)
+ {
+ psPagePoolEntry->psPage = psPage;
+
+ PagePoolLock();
+ AddEntryToPool(psPagePoolEntry);
+ PagePoolUnlock();
+
+ return;
+ }
+ }
+
+ FreePageToLinux(psPage);
+}
+
+static IMG_VOID
+FreePagePool(IMG_VOID)
+{
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+ PagePoolLock();
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ PVR_TRACE(("%s: Freeing %d pages from pool", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+#else
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+ PVR_ASSERT(list_empty(&g_sPagePoolList));
+#endif
+
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ FreePageToLinux(psPagePoolEntry->psPage);
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+ }
+
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+
+ PagePoolUnlock();
+}
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+#if defined(PVRSRV_NEED_PVR_ASSERT)
+static struct shrinker g_sShrinker;
+#endif
+
+static int
+ShrinkPagePool(struct shrinker *psShrinker, struct shrink_control *psShrinkControl)
+{
+ unsigned long uNumToScan = psShrinkControl->nr_to_scan;
+
+ PVR_ASSERT(psShrinker == &g_sShrinker);
+ (void)psShrinker;
+
+ if (uNumToScan != 0)
+ {
+ LinuxPagePoolEntry *psPagePoolEntry, *psTempPoolEntry;
+
+ PVR_TRACE(("%s: Number to scan: %ld", __FUNCTION__, uNumToScan));
+ PVR_TRACE(("%s: Pages in pool before scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+
+ if (!PagePoolTrylock())
+ {
+ PVR_TRACE(("%s: Couldn't get page pool lock", __FUNCTION__));
+ return -1;
+ }
+
+ list_for_each_entry_safe(psPagePoolEntry, psTempPoolEntry, &g_sPagePoolList, sPagePoolItem)
+ {
+ RemoveEntryFromPool(psPagePoolEntry);
+
+ FreePageToLinux(psPagePoolEntry->psPage);
+ LinuxPagePoolEntryFree(psPagePoolEntry);
+
+ if (--uNumToScan == 0)
+ {
+ break;
+ }
+ }
+
+ if (list_empty(&g_sPagePoolList))
+ {
+ PVR_ASSERT(atomic_read(&g_sPagePoolEntryCount) == 0);
+ }
+
+ PagePoolUnlock();
+
+ PVR_TRACE(("%s: Pages in pool after scan: %d", __FUNCTION__, atomic_read(&g_sPagePoolEntryCount)));
+ }
+
+ return atomic_read(&g_sPagePoolEntryCount);
+}
+#endif
+
+static IMG_BOOL
+AllocPages(IMG_UINT32 ui32AreaFlags, struct page ***pppsPageList, IMG_HANDLE *phBlockPageList, IMG_UINT32 ui32NumPages, IMG_BOOL *pbFromPagePool)
+{
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+ IMG_INT32 i; /* Must be signed; see "for" loop conditions */
+ PVRSRV_ERROR eError;
+ IMG_BOOL bFromPagePool = IMG_FALSE;
+
+ eError = OSAllocMem(0, sizeof(*ppsPageList) * ui32NumPages, (IMG_VOID **)&ppsPageList, &hBlockPageList,
+ "Array of pages");
+ if (eError != PVRSRV_OK)
+ {
+ goto failed_page_list_alloc;
+ }
+
+ *pbFromPagePool = IMG_TRUE;
+ for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+ {
+ ppsPageList[i] = AllocPage(ui32AreaFlags, &bFromPagePool);
+ if (!ppsPageList[i])
+ {
+ goto failed_alloc_pages;
+ }
+ *pbFromPagePool &= bFromPagePool;
+ }
+
+ *pppsPageList = ppsPageList;
+ *phBlockPageList = hBlockPageList;
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
+ ppsPageList,
+ 0,
+ 0,
+ NULL,
+ PAGES_TO_BYTES(ui32NumPages),
+ "unknown",
+ 0
+ );
+#endif
+
+ return IMG_TRUE;
+
+failed_alloc_pages:
+ for(i--; i >= 0; i--)
+ {
+ FreePage(*pbFromPagePool, ppsPageList[i]);
+ }
+ (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
+
+failed_page_list_alloc:
+ return IMG_FALSE;
+}
+
+
+static IMG_VOID
+FreePages(IMG_BOOL bToPagePool, struct page **ppsPageList, IMG_HANDLE hBlockPageList, IMG_UINT32 ui32NumPages)
+{
+ IMG_INT32 i;
+
+ for(i = 0; i < (IMG_INT32)ui32NumPages; i++)
+ {
+ FreePage(bToPagePool, ppsPageList[i]);
+ }
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, ppsPageList, __FILE__, __LINE__);
+#endif
+
+ (IMG_VOID) OSFreeMem(0, sizeof(*ppsPageList) * ui32NumPages, ppsPageList, hBlockPageList);
+}
+
+
LinuxMemArea *
NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
{
- LinuxMemArea *psLinuxMemArea;
+ LinuxMemArea *psLinuxMemArea = NULL;
IMG_VOID *pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ IMG_UINT32 ui32NumPages = 0;
+ struct page **ppsPageList = NULL;
+ IMG_HANDLE hBlockPageList;
+#endif
+ IMG_BOOL bFromPagePool = IMG_FALSE;
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
goto failed;
}
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+
+ if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+ {
+ goto failed;
+ }
+
+ pvCpuVAddr = VMapWrapper(ppsPageList, ui32NumPages, ui32AreaFlags);
+#else /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
pvCpuVAddr = VMallocWrapper(ui32Bytes, ui32AreaFlags);
- if(!pvCpuVAddr)
+ if (!pvCpuVAddr)
{
goto failed;
}
-
+/* PG_reserved was deprecated in linux-2.6.15 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
-
+ /* Reserve those pages to allow them to be re-mapped to user space */
ReservePages(pvCpuVAddr, ui32Bytes);
#endif
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_VMALLOC;
psLinuxMemArea->uData.sVmalloc.pvVmallocAddress = pvCpuVAddr;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ psLinuxMemArea->uData.sVmalloc.ppsPageList = ppsPageList;
+ psLinuxMemArea->uData.sVmalloc.hBlockPageList = hBlockPageList;
+#endif
psLinuxMemArea->ui32ByteSize = ui32Bytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
@@ -612,16 +1005,41 @@ NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
#endif
-
- if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
- OSInvalidateCPUCacheRangeKM(psLinuxMemArea, pvCpuVAddr, ui32Bytes);
+ /* This works around a problem where Linux will not invalidate
+ * the cache for physical memory it frees that is direct mapped.
+ *
+ * As a result, cache entries remain that may be subsequently flushed
+ * to these physical pages after they have been allocated for another
+ * purpose. For a subsequent cached use of this memory, that is not a
+ * problem, but if we are allocating uncached or write-combined memory,
+ * and bypassing the cache, it can cause subsequent uncached writes to
+ * the memory to be replaced with junk from the cache.
+ *
+ * If the pages are from our page cache, no cache invalidate is needed.
+ *
+ * This just handles the __vmalloc() case (when we have a kernel virtual
+ * address range). The alloc_pages() path is handled in mmap.c.
+ */
+ if (AreaIsUncached(ui32AreaFlags) && !bFromPagePool)
+ {
+ OSInvalidateCPUCacheRangeKM(psLinuxMemArea, 0, pvCpuVAddr, ui32Bytes);
+ }
return psLinuxMemArea;
failed:
PVR_DPF((PVR_DBG_ERROR, "%s: failed!", __FUNCTION__));
- if(psLinuxMemArea)
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ if (ppsPageList)
+ {
+ FreePages(bFromPagePool, ppsPageList, hBlockPageList, ui32NumPages);
+ }
+#endif
+ if (psLinuxMemArea)
+ {
LinuxMemAreaStructFree(psLinuxMemArea);
+ }
+
return NULL;
}
@@ -629,6 +1047,12 @@ failed:
IMG_VOID
FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
{
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+#endif
+
PVR_ASSERT(psLinuxMemArea);
PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_VMALLOC);
PVR_ASSERT(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
@@ -637,20 +1061,34 @@ FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea)
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
+ PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
+ __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
+
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ VUnmapWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ppsPageList = psLinuxMemArea->uData.sVmalloc.ppsPageList;
+ hBlockPageList = psLinuxMemArea->uData.sVmalloc.hBlockPageList;
+
+ FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+#else
+/* PG_reserved was deprecated in linux-2.6.15 */
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
- UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
+ UnreservePages(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress,
psLinuxMemArea->ui32ByteSize);
#endif
- PVR_DPF((PVR_DBG_MESSAGE,"%s: pvCpuVAddr: %p",
- __FUNCTION__, psLinuxMemArea->uData.sVmalloc.pvVmallocAddress));
VFreeWrapper(psLinuxMemArea->uData.sVmalloc.pvVmallocAddress);
+#endif /* defined(PVR_LINUX_MEM_AREA_USE_VMAP) */
LinuxMemAreaStructFree(psLinuxMemArea);
}
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
+/* Reserve pages of memory in order that they're not automatically
+ deallocated after the last user reference dies. */
static IMG_VOID
ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
{
@@ -668,6 +1106,7 @@ ReservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
}
+/* Un-reserve pages of memory in order that they can be freed. */
static IMG_VOID
UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
{
@@ -683,7 +1122,7 @@ UnreservePages(IMG_VOID *pvAddress, IMG_UINT32 ui32Length)
#endif
}
}
-#endif
+#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15)) */
IMG_VOID *
@@ -695,10 +1134,9 @@ _IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
{
IMG_VOID *pvIORemapCookie;
- switch(ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
+ switch (ui32MappingFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
case PVRSRV_HAP_CACHED:
- case PVRSRV_HAP_SMART:
pvIORemapCookie = (IMG_VOID *)IOREMAP(BasePAddr.uiAddr, ui32Bytes);
break;
case PVRSRV_HAP_WRITECOMBINE:
@@ -713,7 +1151,7 @@ _IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
}
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- if(pvIORemapCookie)
+ if (pvIORemapCookie)
{
DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_IOREMAP,
pvIORemapCookie,
@@ -723,7 +1161,7 @@ _IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
ui32Bytes,
pszFileName,
ui32Line
- );
+ );
}
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
@@ -756,13 +1194,13 @@ NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
IMG_VOID *pvIORemapCookie;
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
pvIORemapCookie = IORemapWrapper(BasePAddr, ui32Bytes, ui32AreaFlags);
- if(!pvIORemapCookie)
+ if (!pvIORemapCookie)
{
LinuxMemAreaStructFree(psLinuxMemArea);
return NULL;
@@ -799,6 +1237,16 @@ FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea)
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Avoid using remap_pfn_range on RAM, if possible. On x86 systems, with
+ * PAT enabled, remap_pfn_range checks the page attributes requested by
+ * remap_pfn_range against those of the direct kernel mapping for those
+ * pages (if any). This is rather annoying if the pages have been obtained
+ * with alloc_pages, where we just ask for raw pages; we don't care about
+ * the direct mapping. This latter issue arises when device memory is
+ * exported from one process to another. Services implements this
+ * using memory wrapping, which ends up creating an external KV memory area.
+ */
static IMG_BOOL
TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig)
{
@@ -806,7 +1254,10 @@ TreatExternalPagesAsContiguous(IMG_SYS_PHYADDR *psSysPhysAddr, IMG_UINT32 ui32By
IMG_UINT32 ui32AddrChk;
IMG_UINT32 ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
-
+ /*
+ * If bPhysContig is IMG_TRUE, we must assume psSysPhysAddr points
+ * to the address of the first page, not an array of page addresses.
+ */
for (ui32 = 0, ui32AddrChk = psSysPhysAddr[0].uiAddr;
ui32 < ui32NumPages;
ui32++, ui32AddrChk = (bPhysContig) ? (ui32AddrChk + PAGE_SIZE) : psSysPhysAddr[ui32].uiAddr)
@@ -843,7 +1294,7 @@ LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *p
LinuxMemArea *psLinuxMemArea;
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
@@ -896,12 +1347,12 @@ NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
-
+ /* Nothing to activly do. We just keep a record of the physical range. */
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_IO;
psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr = BasePAddr.uiAddr;
psLinuxMemArea->ui32ByteSize = ui32Bytes;
@@ -917,7 +1368,7 @@ NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr,
ui32Bytes,
"unknown",
0
- );
+ );
#endif
#if defined(DEBUG_LINUX_MEM_AREAS)
@@ -942,7 +1393,7 @@ FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea)
(IMG_VOID *)psLinuxMemArea->uData.sIO.CPUPhysAddr.uiAddr, __FILE__, __LINE__);
#endif
-
+ /* Nothing more to do than free the LinuxMemArea struct */
LinuxMemAreaStructFree(psLinuxMemArea);
}
@@ -952,68 +1403,33 @@ LinuxMemArea *
NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
{
LinuxMemArea *psLinuxMemArea;
- IMG_UINT32 ui32PageCount;
- struct page **pvPageList;
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
IMG_HANDLE hBlockPageList;
- IMG_INT32 i;
- PVRSRV_ERROR eError;
-
+ IMG_BOOL bFromPagePool;
+
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
goto failed_area_alloc;
}
- ui32PageCount = RANGE_TO_PAGES(ui32Bytes);
- eError = OSAllocMem(0, sizeof(*pvPageList) * ui32PageCount, (IMG_VOID **)&pvPageList, &hBlockPageList,
- "Array of pages");
- if(eError != PVRSRV_OK)
- {
- goto failed_page_list_alloc;
- }
-
- for(i=0; i<(IMG_INT32)ui32PageCount; i++)
- {
- pvPageList[i] = alloc_pages(GFP_KERNEL | __GFP_HIGHMEM, 0);
- if(!pvPageList[i])
- {
- goto failed_alloc_pages;
- }
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
- SetPageReserved(pvPageList[i]);
-#else
- mem_map_reserve(pvPageList[i]);
-#endif
-#endif
+ ui32NumPages = RANGE_TO_PAGES(ui32Bytes);
+ if (!AllocPages(ui32AreaFlags, &ppsPageList, &hBlockPageList, ui32NumPages, &bFromPagePool))
+ {
+ goto failed_alloc_pages;
}
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES,
- pvPageList,
- 0,
- 0,
- NULL,
- PAGE_ALIGN(ui32Bytes),
- "unknown",
- 0
- );
-#endif
-
psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ALLOC_PAGES;
- psLinuxMemArea->uData.sPageList.pvPageList = pvPageList;
+ psLinuxMemArea->uData.sPageList.ppsPageList = ppsPageList;
psLinuxMemArea->uData.sPageList.hBlockPageList = hBlockPageList;
psLinuxMemArea->ui32ByteSize = ui32Bytes;
psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
-
- if(ui32AreaFlags & (PVRSRV_HAP_WRITECOMBINE | PVRSRV_HAP_UNCACHED))
- {
- psLinuxMemArea->bNeedsCacheInvalidate = IMG_TRUE;
- }
+ /* We defer the cache flush to the first user mapping of this memory */
+ psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags) && !bFromPagePool;
#if defined(DEBUG_LINUX_MEM_AREAS)
DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
@@ -1022,13 +1438,6 @@ NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags)
return psLinuxMemArea;
failed_alloc_pages:
- for(i--; i >= 0; i--)
- {
- __free_pages(pvPageList[i], 0);
- }
- (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
- psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
-failed_page_list_alloc:
LinuxMemAreaStructFree(psLinuxMemArea);
failed_area_alloc:
PVR_DPF((PVR_DBG_ERROR, "%s: failed", __FUNCTION__));
@@ -1040,10 +1449,9 @@ failed_area_alloc:
IMG_VOID
FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
{
- IMG_UINT32 ui32PageCount;
- struct page **pvPageList;
+ IMG_UINT32 ui32NumPages;
+ struct page **ppsPageList;
IMG_HANDLE hBlockPageList;
- IMG_INT32 i;
PVR_ASSERT(psLinuxMemArea);
PVR_ASSERT(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_ALLOC_PAGES);
@@ -1052,38 +1460,162 @@ FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea)
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
- ui32PageCount = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
- pvPageList = psLinuxMemArea->uData.sPageList.pvPageList;
+ ui32NumPages = RANGE_TO_PAGES(psLinuxMemArea->ui32ByteSize);
+ ppsPageList = psLinuxMemArea->uData.sPageList.ppsPageList;
hBlockPageList = psLinuxMemArea->uData.sPageList.hBlockPageList;
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, pvPageList, __FILE__, __LINE__);
-#endif
+ FreePages(CanFreeToPool(psLinuxMemArea), ppsPageList, hBlockPageList, ui32NumPages);
+
+ LinuxMemAreaStructFree(psLinuxMemArea);
+}
+
+#if defined(CONFIG_ION_OMAP)
+
+#include "env_perproc.h"
- for(i=0;i<(IMG_INT32)ui32PageCount;i++)
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+
+extern struct ion_client *gpsIONClient;
+
+LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
+{
+ const IMG_UINT32 ui32AllocDataLen =
+ offsetof(struct omap_ion_tiler_alloc_data, handle);
+ struct omap_ion_tiler_alloc_data asAllocData[2] = {};
+ u32 *pu32PageAddrs[2] = { NULL, NULL };
+ IMG_UINT32 i, ui32NumHandlesPerFd;
+ IMG_BYTE *pbPrivData = pvPrivData;
+ IMG_CPU_PHYADDR *pCPUPhysAddrs;
+ int iNumPages[2] = { 0, 0 };
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = LinuxMemAreaStructAlloc();
+ if (!psLinuxMemArea)
{
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15))
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
- ClearPageReserved(pvPageList[i]);
-#else
- mem_map_reserve(pvPageList[i]);
-#endif
-#endif
- if (psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_SMART)
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate LinuxMemArea struct", __func__));
+ goto err_out;
+ }
+
+ /* Depending on the UM config, userspace might give us info for
+ * one or two ION allocations. Divide the total size of data we
+ * were given by this ui32AllocDataLen, and check it's 1 or 2.
+ * Otherwise abort.
+ */
+ BUG_ON(ui32PrivDataLength != ui32AllocDataLen &&
+ ui32PrivDataLength != ui32AllocDataLen * 2);
+ ui32NumHandlesPerFd = ui32PrivDataLength / ui32AllocDataLen;
+
+ /* Shuffle the alloc data into separate Y & UV bits and
+ * make two separate allocations via the tiler.
+ */
+ for(i = 0; i < ui32NumHandlesPerFd; i++)
+ {
+ memcpy(&asAllocData[i], &pbPrivData[i * ui32AllocDataLen], ui32AllocDataLen);
+
+ if (omap_ion_tiler_alloc(gpsIONClient, &asAllocData[i]) < 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate via ion_tiler", __func__));
+ goto err_free;
+ }
+
+ if (omap_tiler_pages(gpsIONClient, asAllocData[i].handle, &iNumPages[i],
+ &pu32PageAddrs[i]) < 0)
{
- // XXX some race here..
- clear_bit(PG_private, &pvPageList[i]->flags);
- clear_bit(PG_private_2, &pvPageList[i]->flags);
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to compute tiler pages", __func__));
+ goto err_free;
}
- __free_pages(pvPageList[i], 0);
}
- (IMG_VOID) OSFreeMem(0, sizeof(*pvPageList) * ui32PageCount, pvPageList, hBlockPageList);
- psLinuxMemArea->uData.sPageList.pvPageList = IMG_NULL;
+ /* Assume the user-allocator has already done the tiler math and that the
+ * number of tiler pages allocated matches any other allocation type.
+ */
+ BUG_ON(ui32Bytes != (iNumPages[0] + iNumPages[1]) * PAGE_SIZE);
+ BUG_ON(sizeof(IMG_CPU_PHYADDR) != sizeof(int));
+
+ /* Glue the page lists together */
+ pCPUPhysAddrs = vmalloc(sizeof(IMG_CPU_PHYADDR) * (iNumPages[0] + iNumPages[1]));
+ if (!pCPUPhysAddrs)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to allocate page list", __func__));
+ goto err_free;
+ }
+ for(i = 0; i < iNumPages[0]; i++)
+ pCPUPhysAddrs[i].uiAddr = pu32PageAddrs[0][i];
+ for(i = 0; i < iNumPages[1]; i++)
+ pCPUPhysAddrs[iNumPages[0] + i].uiAddr = pu32PageAddrs[1][i];
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordAdd(DEBUG_MEM_ALLOC_TYPE_ION,
+ asAllocData[0].handle,
+ 0,
+ 0,
+ NULL,
+ PAGE_ALIGN(ui32Bytes),
+ "unknown",
+ 0
+ );
+#endif
+
+ for(i = 0; i < 2; i++)
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = asAllocData[i].handle;
+
+ psLinuxMemArea->eAreaType = LINUX_MEM_AREA_ION;
+ psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = pCPUPhysAddrs;
+ psLinuxMemArea->ui32ByteSize = ui32Bytes;
+ psLinuxMemArea->ui32AreaFlags = ui32AreaFlags;
+ INIT_LIST_HEAD(&psLinuxMemArea->sMMapOffsetStructList);
+
+ /* We defer the cache flush to the first user mapping of this memory */
+ psLinuxMemArea->bNeedsCacheInvalidate = AreaIsUncached(ui32AreaFlags);
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordAdd(psLinuxMemArea, ui32AreaFlags);
+#endif
+
+err_out:
+ return psLinuxMemArea;
+
+err_free:
+ LinuxMemAreaStructFree(psLinuxMemArea);
+ psLinuxMemArea = IMG_NULL;
+ goto err_out;
+}
+
+
+IMG_VOID
+FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ IMG_UINT32 i;
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ION,
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[0],
+ __FILE__, __LINE__);
+#endif
+
+ for(i = 0; i < 2; i++)
+ {
+ if (!psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i])
+ break;
+ ion_free(gpsIONClient, psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i]);
+ psLinuxMemArea->uData.sIONTilerAlloc.psIONHandle[i] = IMG_NULL;
+ }
+
+ /* free copy of page list, originals are freed by ion_free */
+ vfree(psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs);
+ psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs = IMG_NULL;
LinuxMemAreaStructFree(psLinuxMemArea);
}
+#endif /* defined(CONFIG_ION_OMAP) */
struct page*
LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
@@ -1092,11 +1624,11 @@ LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
IMG_UINT32 ui32PageIndex;
IMG_CHAR *pui8Addr;
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_ALLOC_PAGES:
ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- return psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ return psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
case LINUX_MEM_AREA_VMALLOC:
pui8Addr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
@@ -1104,7 +1636,7 @@ LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea,
return vmalloc_to_page(pui8Addr);
case LINUX_MEM_AREA_SUB_ALLOC:
-
+ /* PRQA S 3670 3 */ /* ignore recursive warning */
return LinuxMemAreaOffsetToPage(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea,
psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset
+ ui32ByteOffset);
@@ -1129,8 +1661,8 @@ KMemCacheCreateWrapper(IMG_CHAR *pszName,
return kmem_cache_create(pszName, Size, Align, ui32Flags, NULL
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
, NULL
-#endif
- );
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22) */
+ );
}
@@ -1164,7 +1696,7 @@ _KMemCacheAllocWrapper(LinuxKMemCache *psCache,
kmem_cache_size(psCache),
pszFileName,
ui32Line
- );
+ );
#else
PVR_UNREFERENCED_PARAMETER(pszFileName);
PVR_UNREFERENCED_PARAMETER(ui32Line);
@@ -1174,30 +1706,6 @@ _KMemCacheAllocWrapper(LinuxKMemCache *psCache,
}
-IMG_VOID
-_KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line)
-{
-#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
- DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE, pvObject, pszFileName, ui32Line);
-#else
- PVR_UNREFERENCED_PARAMETER(pszFileName);
- PVR_UNREFERENCED_PARAMETER(ui32Line);
-#endif
-
- kmem_cache_free(psCache, pvObject);
-}
-
-
-const IMG_CHAR *
-KMemCacheNameWrapper(LinuxKMemCache *psCache)
-{
- PVR_UNREFERENCED_PARAMETER(psCache);
-
-
- return "";
-}
-
-
LinuxMemArea *
NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
IMG_UINT32 ui32ByteOffset,
@@ -1208,7 +1716,7 @@ NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
PVR_ASSERT((ui32ByteOffset+ui32Bytes) <= psParentLinuxMemArea->ui32ByteSize);
psLinuxMemArea = LinuxMemAreaStructAlloc();
- if(!psLinuxMemArea)
+ if (!psLinuxMemArea)
{
return NULL;
}
@@ -1242,7 +1750,7 @@ FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
DebugLinuxMemAreaRecordRemove(psLinuxMemArea);
#endif
-
+ /* Nothing more to do than free the LinuxMemArea structure */
LinuxMemAreaStructFree(psLinuxMemArea);
}
@@ -1251,14 +1759,15 @@ FreeSubLinuxMemArea(LinuxMemArea *psLinuxMemArea)
static LinuxMemArea *
LinuxMemAreaStructAlloc(IMG_VOID)
{
+/* debug */
#if 0
LinuxMemArea *psLinuxMemArea;
- psLinuxMemArea = kmem_cache_alloc(psLinuxMemAreaCache, GFP_KERNEL);
+ psLinuxMemArea = kmem_cache_alloc(g_PsLinuxMemAreaCache, GFP_KERNEL);
printk(KERN_ERR "%s: psLinuxMemArea=%p\n", __FUNCTION__, psLinuxMemArea);
dump_stack();
return psLinuxMemArea;
#else
- return KMemCacheAllocWrapper(psLinuxMemAreaCache, GFP_KERNEL);
+ return KMemCacheAllocWrapper(g_PsLinuxMemAreaCache, GFP_KERNEL);
#endif
}
@@ -1274,16 +1783,16 @@ LinuxMemAreaStructFree(LinuxMemArea *psLinuxMemArea)
if (psLinuxMemArea->buf)
drm_gem_object_unreference_unlocked(psLinuxMemArea->buf);
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
- KMemCacheFreeWrapper(psLinuxMemAreaCache, psLinuxMemArea);
-
-
+ KMemCacheFreeWrapper(g_PsLinuxMemAreaCache, psLinuxMemArea);
+ /* debug */
+ //printk(KERN_ERR "%s(%p)\n", __FUNCTION__, psLinuxMemArea);
}
IMG_VOID
LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
{
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_VMALLOC:
FreeVMallocLinuxMemArea(psLinuxMemArea);
@@ -1294,15 +1803,18 @@ LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea)
case LINUX_MEM_AREA_IOREMAP:
FreeIORemapLinuxMemArea(psLinuxMemArea);
break;
- case LINUX_MEM_AREA_EXTERNAL_KV:
- FreeExternalKVLinuxMemArea(psLinuxMemArea);
- break;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ FreeExternalKVLinuxMemArea(psLinuxMemArea);
+ break;
case LINUX_MEM_AREA_IO:
FreeIOLinuxMemArea(psLinuxMemArea);
break;
case LINUX_MEM_AREA_SUB_ALLOC:
FreeSubLinuxMemArea(psLinuxMemArea);
break;
+ case LINUX_MEM_AREA_ION:
+ FreeIONLinuxMemArea(psLinuxMemArea);
+ break;
default:
PVR_DPF((PVR_DBG_ERROR, "%s: Unknown are type (%d)\n",
__FUNCTION__, psLinuxMemArea->eAreaType));
@@ -1320,21 +1832,21 @@ DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
LinuxLockMutex(&g_sDebugMutex);
- if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
g_LinuxMemAreaWaterMark += psLinuxMemArea->ui32ByteSize;
- if(g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
+ if (g_LinuxMemAreaWaterMark > g_LinuxMemAreaHighWaterMark)
{
g_LinuxMemAreaHighWaterMark = g_LinuxMemAreaWaterMark;
}
}
g_LinuxMemAreaCount++;
-
+ /* Create a new memory allocation record */
psNewRecord = kmalloc(sizeof(DEBUG_LINUX_MEM_AREA_REC), GFP_KERNEL);
- if(psNewRecord)
+ if (psNewRecord)
{
-
+ /* Record the allocation */
psNewRecord->psLinuxMemArea = psLinuxMemArea;
psNewRecord->ui32Flags = ui32Flags;
psNewRecord->pid = OSGetCurrentProcessIDKM();
@@ -1348,16 +1860,16 @@ DebugLinuxMemAreaRecordAdd(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Flags)
__FUNCTION__));
}
-
+ /* Sanity check the flags */
pi8FlagsString = HAPFlagsToString(ui32Flags);
- if(strstr(pi8FlagsString, "UNKNOWN"))
+ if (strstr(pi8FlagsString, "UNKNOWN"))
{
PVR_DPF((PVR_DBG_ERROR,
"%s: Unexpected flags (0x%08x) associated with psLinuxMemArea @ %p",
__FUNCTION__,
ui32Flags,
psLinuxMemArea));
-
+ //dump_stack();
}
LinuxUnLockMutex(&g_sDebugMutex);
@@ -1371,7 +1883,7 @@ static IMG_VOID* MatchLinuxMemArea_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRe
LinuxMemArea *psLinuxMemArea;
psLinuxMemArea = va_arg(va, LinuxMemArea*);
- if(psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
+ if (psCurrentRecord->psLinuxMemArea == psLinuxMemArea)
{
return psCurrentRecord;
}
@@ -1392,6 +1904,7 @@ DebugLinuxMemAreaRecordFind(LinuxMemArea *psLinuxMemArea)
MatchLinuxMemArea_AnyVaCb,
psLinuxMemArea);
+/*exit_unlock:*/
LinuxUnLockMutex(&g_sDebugMutex);
return psCurrentRecord;
@@ -1405,19 +1918,19 @@ DebugLinuxMemAreaRecordRemove(LinuxMemArea *psLinuxMemArea)
LinuxLockMutex(&g_sDebugMutex);
- if(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
+ if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
g_LinuxMemAreaWaterMark -= psLinuxMemArea->ui32ByteSize;
}
g_LinuxMemAreaCount--;
-
+ /* Locate the corresponding allocation entry */
psCurrentRecord = List_DEBUG_LINUX_MEM_AREA_REC_Any_va(g_LinuxMemAreaRecords,
MatchLinuxMemArea_AnyVaCb,
psLinuxMemArea);
- if(psCurrentRecord)
+ if (psCurrentRecord)
{
-
+ /* Unlink the allocation record */
List_DEBUG_LINUX_MEM_AREA_REC_Remove(psCurrentRecord);
kfree(psCurrentRecord);
}
@@ -1439,7 +1952,7 @@ LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
{
return NULL;
}
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_VMALLOC:
return psLinuxMemArea->uData.sVmalloc.pvVmallocAddress;
@@ -1450,8 +1963,8 @@ LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea)
case LINUX_MEM_AREA_SUB_ALLOC:
{
IMG_CHAR *pAddr =
- LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
- if(!pAddr)
+ LinuxMemAreaToCpuVAddr(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea); /* PRQA S 3670 */ /* ignore recursive warning */
+ if (!pAddr)
{
return NULL;
}
@@ -1473,7 +1986,7 @@ LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
return CpuPAddr;
}
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_IOREMAP:
{
@@ -1513,11 +2026,18 @@ LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
CpuPAddr.uiAddr = VMallocToPhys(pCpuVAddr);
break;
}
+ case LINUX_MEM_AREA_ION:
+ {
+ IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
+ CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageIndex];
+ CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
+ break;
+ }
case LINUX_MEM_AREA_ALLOC_PAGES:
{
struct page *page;
IMG_UINT32 ui32PageIndex = PHYS_TO_PFN(ui32ByteOffset);
- page = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageIndex];
+ page = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageIndex];
CpuPAddr.uiAddr = page_to_phys(page);
CpuPAddr.uiAddr += ADDR_TO_PAGE_OFFSET(ui32ByteOffset);
break;
@@ -1546,22 +2066,23 @@ LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset)
IMG_BOOL
LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
{
- switch(psLinuxMemArea->eAreaType)
+ switch (psLinuxMemArea->eAreaType)
{
case LINUX_MEM_AREA_IOREMAP:
case LINUX_MEM_AREA_IO:
return IMG_TRUE;
- case LINUX_MEM_AREA_EXTERNAL_KV:
- return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+ case LINUX_MEM_AREA_EXTERNAL_KV:
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+ case LINUX_MEM_AREA_ION:
case LINUX_MEM_AREA_VMALLOC:
case LINUX_MEM_AREA_ALLOC_PAGES:
- return IMG_FALSE;
+ return IMG_FALSE;
case LINUX_MEM_AREA_SUB_ALLOC:
-
- return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
+ /* PRQA S 3670 1 */ /* ignore recursive warning */
+ return LinuxMemAreaPhysIsContig(psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea);
default:
PVR_DPF((PVR_DBG_ERROR, "%s: Unknown LinuxMemArea type (%d)\n",
@@ -1575,8 +2096,10 @@ LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea)
const IMG_CHAR *
LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
{
-
- switch(eMemAreaType)
+ /* Note we explicitly check the types instead of e.g.
+ * using the type to index an array of strings so
+ * we remain orthogonal to enum changes */
+ switch (eMemAreaType)
{
case LINUX_MEM_AREA_IOREMAP:
return "LINUX_MEM_AREA_IOREMAP";
@@ -1590,6 +2113,8 @@ LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
return "LINUX_MEM_AREA_SUB_ALLOC";
case LINUX_MEM_AREA_ALLOC_PAGES:
return "LINUX_MEM_AREA_ALLOC_PAGES";
+ case LINUX_MEM_AREA_ION:
+ return "LINUX_MEM_AREA_ION";
default:
PVR_ASSERT(0);
}
@@ -1601,7 +2126,7 @@ LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType)
#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
{
- if(start)
+ if (start)
{
LinuxLockMutex(&g_sDebugMutex);
}
@@ -1610,7 +2135,7 @@ static void ProcSeqStartstopDebugMutex(struct seq_file *sfile, IMG_BOOL start)
LinuxUnLockMutex(&g_sDebugMutex);
}
}
-#endif
+#endif /* defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
#if defined(DEBUG_LINUX_MEM_AREAS)
@@ -1627,7 +2152,7 @@ static IMG_VOID* DecOffMemAreaRec_AnyVaCb(DEBUG_LINUX_MEM_AREA_REC *psNode, va_l
}
}
-
+/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */
static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
{
DEBUG_LINUX_MEM_AREA_REC *psRecord;
@@ -1641,7 +2166,7 @@ static void* ProcSeqNextMemArea(struct seq_file *sfile,void* el,loff_t off)
static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
{
DEBUG_LINUX_MEM_AREA_REC *psRecord;
- if(!off)
+ if (!off)
{
return PVR_PROC_SEQ_START_TOKEN;
}
@@ -1657,11 +2182,11 @@ static void* ProcSeqOff2ElementMemArea(struct seq_file * sfile, loff_t off)
static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
{
DEBUG_LINUX_MEM_AREA_REC *psRecord = (DEBUG_LINUX_MEM_AREA_REC*)el;
- if(el == PVR_PROC_SEQ_START_TOKEN)
+ if (el == PVR_PROC_SEQ_START_TOKEN)
{
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
- seq_printf( sfile,
+ seq_printf(sfile,
"Number of Linux Memory Areas: %u\n"
"At the current water mark these areas correspond to %u bytes (excluding SUB areas)\n"
"At the highest water mark these areas corresponded to %u bytes (excluding SUB areas)\n"
@@ -1677,23 +2202,23 @@ static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
"Bytes",
"Pid",
"Flags"
- );
+ );
#else
- seq_printf( sfile,
+ seq_printf(sfile,
"<mem_areas_header>\n"
"\t<count>%u</count>\n"
- "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n"
- "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n"
+ "\t<watermark key=\"mar0\" description=\"current\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */
+ "\t<watermark key=\"mar1\" description=\"high\" bytes=\"%u\"/>\n" /* (excluding SUB areas) */
"</mem_areas_header>\n",
g_LinuxMemAreaCount,
g_LinuxMemAreaWaterMark,
g_LinuxMemAreaHighWaterMark
- );
+ );
#endif
return;
}
- seq_printf( sfile,
+ seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"%8p %-24s %8p %08x %-8d %-5u %08x=(%s)\n",
#else
@@ -1702,9 +2227,9 @@ static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
"\t<type>%s</type>\n"
"\t<cpu_virtual>%8p</cpu_virtual>\n"
"\t<cpu_physical>%08x</cpu_physical>\n"
- "\t<bytes>%ld</bytes>\n"
+ "\t<bytes>%d</bytes>\n"
"\t<pid>%u</pid>\n"
- "\t<flags>%08lx</flags>\n"
+ "\t<flags>%08x</flags>\n"
"\t<flags_string>%s</flags_string>\n"
"</linux_mem_area>\n",
#endif
@@ -1716,11 +2241,11 @@ static void ProcSeqShowMemArea(struct seq_file *sfile,void* el)
psRecord->pid,
psRecord->ui32Flags,
HAPFlagsToString(psRecord->ui32Flags)
- );
+ );
}
-#endif
+#endif /* DEBUG_LINUX_MEM_AREAS */
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
@@ -1739,7 +2264,7 @@ static IMG_VOID* DecOffMemAllocRec_AnyVaCb(DEBUG_MEM_ALLOC_REC *psNode, va_list
}
-
+/* seq_file version of generating output, for reference check proc.c:CreateProcReadEntrySeq */
static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off)
{
DEBUG_MEM_ALLOC_REC *psRecord;
@@ -1748,9 +2273,9 @@ static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off
DecOffMemAllocRec_AnyVaCb,
&off);
#if defined(DEBUG_LINUX_XML_PROC_FILES)
- if(!psRecord)
+ if (!psRecord)
{
- seq_printf( sfile, "</meminfo>\n");
+ seq_printf(sfile, "</meminfo>\n");
}
#endif
@@ -1760,7 +2285,7 @@ static void* ProcSeqNextMemoryRecords(struct seq_file *sfile,void* el,loff_t off
static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
{
DEBUG_MEM_ALLOC_REC *psRecord;
- if(!off)
+ if (!off)
{
return PVR_PROC_SEQ_START_TOKEN;
}
@@ -1771,9 +2296,9 @@ static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
&off);
#if defined(DEBUG_LINUX_XML_PROC_FILES)
- if(!psRecord)
+ if (!psRecord)
{
- seq_printf( sfile, "</meminfo>\n");
+ seq_printf(sfile, "</meminfo>\n");
}
#endif
@@ -1783,64 +2308,78 @@ static void* ProcSeqOff2ElementMemoryRecords(struct seq_file *sfile, loff_t off)
static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
{
DEBUG_MEM_ALLOC_REC *psRecord = (DEBUG_MEM_ALLOC_REC*)el;
- if(el == PVR_PROC_SEQ_START_TOKEN)
+ if (el == PVR_PROC_SEQ_START_TOKEN)
{
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
-
- seq_printf( sfile, "%-60s: %d bytes\n",
+ /* NOTE: If you update this code, please also update the XML varient below
+ * too! */
+
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via kmalloc",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via kmalloc",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via vmalloc",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via vmalloc",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via alloc_pages",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via alloc_pages",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via ioremap",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via ioremap",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes reserved for \"IO\" memory areas",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated for \"IO\" memory areas",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Current Water Mark of bytes allocated via kmem_cache_alloc",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"Highest Water Mark of bytes allocated via kmem_cache_alloc",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Current Water Mark of bytes mapped via vmap",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+ seq_printf(sfile, "%-60s: %d bytes\n",
+ "Highest Water Mark of bytes mapped via vmap",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ seq_printf(sfile, "%-60s: %d pages\n",
+ "Number of pages in page pool",
+ atomic_read(&g_sPagePoolEntryCount));
+#endif
seq_printf( sfile, "\n");
-
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Current Water Mark for memory allocated from system RAM",
- g_SysRAMWaterMark);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ SysRAMTrueWaterMark());
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Highest Water Mark for memory allocated from system RAM",
g_SysRAMHighWaterMark);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Current Water Mark for memory allocated from IO memory",
g_IOMemWaterMark);
- seq_printf( sfile, "%-60s: %d bytes\n",
+ seq_printf(sfile, "%-60s: %d bytes\n",
"The Highest Water Mark for memory allocated from IO memory",
g_IOMemHighWaterMark);
seq_printf( sfile, "\n");
- seq_printf( sfile, "Details for all known allocations:\n"
+ seq_printf(sfile, "Details for all known allocations:\n"
"%-16s %-8s %-8s %-10s %-5s %-10s %s\n",
"Type",
"CpuVAddr",
@@ -1850,70 +2389,84 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
"PrivateData",
"Filename:Line");
-#else
-
+#else /* DEBUG_LINUX_XML_PROC_FILES */
- seq_printf( sfile, "<meminfo>\n<meminfo_header>\n");
- seq_printf( sfile,
+ /* Note: If you want to update the description property of a watermark
+ * ensure that the key property remains unchanged so that watermark data
+ * logged over time from different driver revisions may remain comparable
+ */
+ seq_printf(sfile, "<meminfo>\n<meminfo_header>\n");
+ seq_printf(sfile,
"<watermark key=\"mr0\" description=\"kmalloc_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr1\" description=\"kmalloc_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr2\" description=\"vmalloc_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr3\" description=\"vmalloc_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMALLOC]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr4\" description=\"alloc_pages_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr5\" description=\"alloc_pages_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr6\" description=\"ioremap_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr7\" description=\"ioremap_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IOREMAP]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr8\" description=\"io_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr9\" description=\"io_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_IO]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr10\" description=\"kmem_cache_current\" bytes=\"%d\"/>\n",
g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr11\" description=\"kmem_cache_high\" bytes=\"%d\"/>\n",
g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE]);
- seq_printf( sfile,"\n" );
-
- seq_printf( sfile,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ seq_printf(sfile,
+ "<watermark key=\"mr12\" description=\"vmap_current\" bytes=\"%d\"/>\n",
+ g_WaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+ seq_printf(sfile,
+ "<watermark key=\"mr13\" description=\"vmap_high\" bytes=\"%d\"/>\n",
+ g_HighWaterMarkData[DEBUG_MEM_ALLOC_TYPE_VMAP]);
+#endif
+ seq_printf(sfile,
"<watermark key=\"mr14\" description=\"system_ram_current\" bytes=\"%d\"/>\n",
- g_SysRAMWaterMark);
- seq_printf( sfile,
+ SysRAMTrueWaterMark());
+ seq_printf(sfile,
"<watermark key=\"mr15\" description=\"system_ram_high\" bytes=\"%d\"/>\n",
g_SysRAMHighWaterMark);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr16\" description=\"system_io_current\" bytes=\"%d\"/>\n",
g_IOMemWaterMark);
- seq_printf( sfile,
+ seq_printf(sfile,
"<watermark key=\"mr17\" description=\"system_io_high\" bytes=\"%d\"/>\n",
g_IOMemHighWaterMark);
- seq_printf( sfile, "</meminfo_header>\n");
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ seq_printf(sfile,
+ "<watermark key=\"mr18\" description=\"page_pool_current\" bytes=\"%d\"/>\n",
+ PAGES_TO_BYTES(atomic_read(&g_sPagePoolEntryCount)));
+#endif
+ seq_printf(sfile, "</meminfo_header>\n");
-#endif
+#endif /* DEBUG_LINUX_XML_PROC_FILES */
return;
}
- if(psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
+ if (psRecord->eAllocType != DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE)
{
- seq_printf( sfile,
+ seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
#else
@@ -1939,7 +2492,7 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
}
else
{
- seq_printf( sfile,
+ seq_printf(sfile,
#if !defined(DEBUG_LINUX_XML_PROC_FILES)
"%-16s %-8p %08x %-10d %-5d %-10s %s:%d\n",
#else
@@ -1965,10 +2518,11 @@ static void ProcSeqShowMemoryRecords(struct seq_file *sfile,void* el)
}
}
-#endif
+#endif /* defined(DEBUG_LINUX_MEMORY_ALLOCATIONS) */
#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
+/* This could be moved somewhere more general */
const IMG_CHAR *
HAPFlagsToString(IMG_UINT32 ui32Flags)
{
@@ -1978,7 +2532,6 @@ HAPFlagsToString(IMG_UINT32 ui32Flags)
IMG_CHAR *apszCacheTypes[] = {
"UNCACHED",
"CACHED",
- "SMART",
"WRITECOMBINE",
"UNKNOWN"
};
@@ -1991,33 +2544,35 @@ HAPFlagsToString(IMG_UINT32 ui32Flags)
"UNKNOWN"
};
-
- if(ui32Flags & PVRSRV_HAP_UNCACHED){
- ui32CacheTypeIndex=0;
- }else if(ui32Flags & PVRSRV_HAP_CACHED){
- ui32CacheTypeIndex=1;
- }else if(ui32Flags & PVRSRV_HAP_SMART){
- ui32CacheTypeIndex=2;
- }else if(ui32Flags & PVRSRV_HAP_WRITECOMBINE){
- ui32CacheTypeIndex=3;
- }else{
- ui32CacheTypeIndex=4;
+ /* FIXME create an enum for the cache type that we can
+ * cast and select so we get compiler warnings when
+ * when this code isn't complete due to new flags */
+ if (ui32Flags & PVRSRV_HAP_UNCACHED) {
+ ui32CacheTypeIndex = 0;
+ } else if (ui32Flags & PVRSRV_HAP_CACHED) {
+ ui32CacheTypeIndex = 1;
+ } else if (ui32Flags & PVRSRV_HAP_WRITECOMBINE) {
+ ui32CacheTypeIndex = 2;
+ } else {
+ ui32CacheTypeIndex = 3;
PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type (%u)",
__FUNCTION__, (ui32Flags & PVRSRV_HAP_CACHETYPE_MASK)));
}
-
- if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY){
+ /* FIXME create an enum for the map type that we can
+ * cast and select so we get compiler warnings when
+ * when this code isn't complete due to new flags */
+ if (ui32Flags & PVRSRV_HAP_KERNEL_ONLY) {
ui32MapTypeIndex = 0;
- }else if(ui32Flags & PVRSRV_HAP_SINGLE_PROCESS){
+ } else if (ui32Flags & PVRSRV_HAP_SINGLE_PROCESS) {
ui32MapTypeIndex = 1;
- }else if(ui32Flags & PVRSRV_HAP_MULTI_PROCESS){
+ } else if (ui32Flags & PVRSRV_HAP_MULTI_PROCESS) {
ui32MapTypeIndex = 2;
- }else if(ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS){
+ } else if (ui32Flags & PVRSRV_HAP_FROM_EXISTING_PROCESS) {
ui32MapTypeIndex = 3;
- }else if(ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL){
+ } else if (ui32Flags & PVRSRV_HAP_NO_CPU_VIRTUAL) {
ui32MapTypeIndex = 4;
- }else{
+ } else {
ui32MapTypeIndex = 5;
PVR_DPF((PVR_DBG_ERROR, "%s: unknown map type (%u)",
__FUNCTION__, (ui32Flags & PVRSRV_HAP_MAPTYPE_MASK)));
@@ -2039,3 +2594,222 @@ HAPFlagsToString(IMG_UINT32 ui32Flags)
}
#endif
+#if defined(DEBUG_LINUX_MEM_AREAS)
+static IMG_VOID LinuxMMCleanup_MemAreas_ForEachCb(DEBUG_LINUX_MEM_AREA_REC *psCurrentRecord)
+{
+ LinuxMemArea *psLinuxMemArea;
+
+ psLinuxMemArea = psCurrentRecord->psLinuxMemArea;
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up Linux memory area (%p), type=%s, size=%d bytes",
+ __FUNCTION__,
+ psCurrentRecord->psLinuxMemArea,
+ LinuxMemAreaTypeToString(psCurrentRecord->psLinuxMemArea->eAreaType),
+ psCurrentRecord->psLinuxMemArea->ui32ByteSize));
+ /* Note this will also remove psCurrentRecord from g_LinuxMemAreaRecords
+ * but that's ok since we have already got a pointer to the next area. */
+ LinuxMemAreaDeepFree(psLinuxMemArea);
+}
+#endif
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+static IMG_VOID LinuxMMCleanup_MemRecords_ForEachVa(DEBUG_MEM_ALLOC_REC *psCurrentRecord)
+
+{
+
+/* It's a bug if anything remains allocated at this point. We
+ * report an error, and simply brute force free anything we find. */
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: Cleaning up memory: "
+ "type=%s "
+ "CpuVAddr=%p "
+ "CpuPAddr=0x%08x, "
+ "allocated @ file=%s,line=%d",
+ __FUNCTION__,
+ DebugMemAllocRecordTypeToString(psCurrentRecord->eAllocType),
+ psCurrentRecord->pvCpuVAddr,
+ psCurrentRecord->ulCpuPAddr,
+ psCurrentRecord->pszFileName,
+ psCurrentRecord->ui32Line));
+ switch (psCurrentRecord->eAllocType)
+ {
+ case DEBUG_MEM_ALLOC_TYPE_KMALLOC:
+ KFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IOREMAP:
+ IOUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_IO:
+ /* Nothing needed except to free the record */
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_IO, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_VMALLOC:
+ VFreeWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES:
+ DebugMemAllocRecordRemove(DEBUG_MEM_ALLOC_TYPE_ALLOC_PAGES, psCurrentRecord->pvKey, __FILE__, __LINE__);
+ break;
+ case DEBUG_MEM_ALLOC_TYPE_KMEM_CACHE:
+ KMemCacheFreeWrapper(psCurrentRecord->pvPrivateData, psCurrentRecord->pvCpuVAddr);
+ break;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ case DEBUG_MEM_ALLOC_TYPE_VMAP:
+ VUnmapWrapper(psCurrentRecord->pvCpuVAddr);
+ break;
+#endif
+ default:
+ PVR_ASSERT(0);
+ }
+}
+#endif
+
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+static struct shrinker g_sShrinker =
+{
+ .shrink = ShrinkPagePool,
+ .seeks = DEFAULT_SEEKS
+};
+
+static IMG_BOOL g_bShrinkerRegistered;
+#endif
+
+IMG_VOID
+LinuxMMCleanup(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ if (g_LinuxMemAreaCount)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: BUG!: There are %d LinuxMemArea allocation unfreed (%d bytes)",
+ __FUNCTION__, g_LinuxMemAreaCount, g_LinuxMemAreaWaterMark));
+ }
+
+ List_DEBUG_LINUX_MEM_AREA_REC_ForEach(g_LinuxMemAreaRecords, LinuxMMCleanup_MemAreas_ForEachCb);
+
+ if (g_SeqFileMemArea)
+ {
+ RemoveProcEntrySeq(g_SeqFileMemArea);
+ }
+ }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+ if (g_bShrinkerRegistered)
+ {
+ unregister_shrinker(&g_sShrinker);
+ }
+#endif
+
+ /*
+ * The page pool must be freed after any remaining mem areas, but before
+ * the remaining memory resources.
+ */
+ FreePagePool();
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+
+ /*
+ * It's a bug if anything remains allocated at this point. We
+ * report an error, and simply brute force free anything we find.
+ */
+ List_DEBUG_MEM_ALLOC_REC_ForEach(g_MemoryRecords, LinuxMMCleanup_MemRecords_ForEachVa);
+
+ if (g_SeqFileMemoryRecords)
+ {
+ RemoveProcEntrySeq(g_SeqFileMemoryRecords);
+ }
+ }
+#endif
+
+ if (g_PsLinuxMemAreaCache)
+ {
+ KMemCacheDestroyWrapper(g_PsLinuxMemAreaCache);
+ }
+
+ if (g_PsLinuxPagePoolCache)
+ {
+ KMemCacheDestroyWrapper(g_PsLinuxPagePoolCache);
+ }
+}
+
+PVRSRV_ERROR
+LinuxMMInit(IMG_VOID)
+{
+#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ LinuxInitMutex(&g_sDebugMutex);
+#endif
+
+#if defined(DEBUG_LINUX_MEM_AREAS)
+ {
+ g_SeqFileMemArea = CreateProcReadEntrySeq(
+ "mem_areas",
+ NULL,
+ ProcSeqNextMemArea,
+ ProcSeqShowMemArea,
+ ProcSeqOff2ElementMemArea,
+ ProcSeqStartstopDebugMutex
+ );
+ if (!g_SeqFileMemArea)
+ {
+ goto failed;
+ }
+ }
+#endif
+
+
+#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
+ {
+ g_SeqFileMemoryRecords = CreateProcReadEntrySeq(
+ "meminfo",
+ NULL,
+ ProcSeqNextMemoryRecords,
+ ProcSeqShowMemoryRecords,
+ ProcSeqOff2ElementMemoryRecords,
+ ProcSeqStartstopDebugMutex
+ );
+ if (!g_SeqFileMemoryRecords)
+ {
+ goto failed;
+ }
+ }
+#endif
+
+ g_PsLinuxMemAreaCache = KMemCacheCreateWrapper("img-mm", sizeof(LinuxMemArea), 0, 0);
+ if (!g_PsLinuxMemAreaCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate mem area kmem_cache", __FUNCTION__));
+ goto failed;
+ }
+
+#if (PVR_LINUX_MEM_AREA_POOL_MAX_PAGES != 0)
+ g_iPagePoolMaxEntries = PVR_LINUX_MEM_AREA_POOL_MAX_PAGES;
+ if (g_iPagePoolMaxEntries <= 0 || g_iPagePoolMaxEntries > INT_MAX/2)
+ {
+ g_iPagePoolMaxEntries = INT_MAX/2;
+ PVR_TRACE(("%s: No limit set for page pool size", __FUNCTION__));
+ }
+ else
+ {
+ PVR_TRACE(("%s: Maximum page pool size: %d", __FUNCTION__, g_iPagePoolMaxEntries));
+ }
+
+ g_PsLinuxPagePoolCache = KMemCacheCreateWrapper("img-mm-pool", sizeof(LinuxPagePoolEntry), 0, 0);
+ if (!g_PsLinuxPagePoolCache)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: failed to allocate page pool kmem_cache", __FUNCTION__));
+ goto failed;
+ }
+#endif
+
+#if defined(PVR_LINUX_MEM_AREA_POOL_ALLOW_SHRINK)
+ register_shrinker(&g_sShrinker);
+ g_bShrinkerRegistered = IMG_TRUE;
+#endif
+
+ return PVRSRV_OK;
+
+failed:
+ LinuxMMCleanup();
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+}
+
diff --git a/sgx/services4/srvkm/env/linux/mm.h b/sgx/services4/srvkm/env/linux/mm.h
index da49083..2bcf408 100644
--- a/sgx/services4/srvkm/env/linux/mm.h
+++ b/sgx/services4/srvkm/env/linux/mm.h
@@ -1,29 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Linux Memory Management.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares various memory management utility functions
+ for Linux.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __IMG_LINUX_MM_H__
#define __IMG_LINUX_MM_H__
@@ -48,6 +65,8 @@
#define ADDR_TO_PAGE_OFFSET(addr) (((unsigned long)(addr)) & (PAGE_SIZE - 1))
+#define PAGES_TO_BYTES(pages) ((pages) << PAGE_SHIFT)
+
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10))
#define REMAP_PFN_RANGE(vma, addr, pfn, size, prot) remap_pfn_range(vma, addr, pfn, size, prot)
#else
@@ -78,33 +97,43 @@ static inline IMG_UINT32 VMallocToPhys(IMG_VOID *pCpuVAddr)
typedef enum {
LINUX_MEM_AREA_IOREMAP,
- LINUX_MEM_AREA_EXTERNAL_KV,
+ LINUX_MEM_AREA_EXTERNAL_KV,
LINUX_MEM_AREA_IO,
LINUX_MEM_AREA_VMALLOC,
LINUX_MEM_AREA_ALLOC_PAGES,
LINUX_MEM_AREA_SUB_ALLOC,
+ LINUX_MEM_AREA_ION,
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ LINUX_MEM_AREA_VMAP,
+#endif
LINUX_MEM_AREA_TYPE_COUNT
}LINUX_MEM_AREA_TYPE;
typedef struct _LinuxMemArea LinuxMemArea;
+/* FIXME - describe this structure. */
struct _LinuxMemArea {
LINUX_MEM_AREA_TYPE eAreaType;
union _uData
{
struct _sIORemap
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
IMG_CPU_PHYADDR CPUPhysAddr;
IMG_VOID *pvIORemapCookie;
}sIORemap;
struct _sExternalKV
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
IMG_BOOL bPhysContig;
union {
-
+ /*
+ * SYSPhysAddr is valid if bPhysContig is true, else
+ * pSysPhysAddr is valid
+ */
IMG_SYS_PHYADDR SysPhysAddr;
IMG_SYS_PHYADDR *pSysPhysAddr;
} uPhysAddr;
@@ -112,44 +141,62 @@ struct _LinuxMemArea {
}sExternalKV;
struct _sIO
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
IMG_CPU_PHYADDR CPUPhysAddr;
}sIO;
struct _sVmalloc
{
-
+ /* Note the memory this represents _is_ implicitly
+ * page aligned _and_ so is its size */
IMG_VOID *pvVmallocAddress;
+#if defined(PVR_LINUX_MEM_AREA_USE_VMAP)
+ struct page **ppsPageList;
+ IMG_HANDLE hBlockPageList;
+#endif
}sVmalloc;
struct _sPageList
{
-
- struct page **pvPageList;
+ /* Note the memory this represents _is_ implicitly
+ * page aligned _and_ so is its size */
+ struct page **ppsPageList;
IMG_HANDLE hBlockPageList;
}sPageList;
+ struct _sIONTilerAlloc
+ {
+ /* Note the memory this represents _is_ implicitly
+ * page aligned _and_ so is its size */
+ IMG_CPU_PHYADDR *pCPUPhysAddrs;
+ struct ion_handle *psIONHandle[2];
+ }sIONTilerAlloc;
struct _sSubAlloc
{
-
+ /* Note: The memory this represents is _not_ implicitly
+ * page aligned, neither is its size */
LinuxMemArea *psParentLinuxMemArea;
IMG_UINT32 ui32ByteOffset;
}sSubAlloc;
}uData;
- IMG_UINT32 ui32ByteSize;
+ IMG_UINT32 ui32ByteSize; /* Size of memory area */
+
+ IMG_UINT32 ui32AreaFlags; /* Flags passed at creation time */
- IMG_UINT32 ui32AreaFlags;
+ IMG_BOOL bMMapRegistered; /* Registered with mmap code */
- IMG_BOOL bMMapRegistered;
+ IMG_BOOL bNeedsCacheInvalidate; /* Cache should be invalidated on first map? */
- IMG_BOOL bNeedsCacheInvalidate;
+ IMG_HANDLE hBMHandle; /* Handle back to BM for this allocation */
-
+ /* List entry for global list of areas registered for mmap */
struct list_head sMMapItem;
-
+ /*
+ * Head of list of all mmap offset structures associated with this
+ * memory area.
+ */
struct list_head sMMapOffsetStructList;
- IMG_HANDLE hSmartCache;
-
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
IMG_HANDLE buf; /* external buffer handle, like a GEM or ION buffer */
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
@@ -162,12 +209,45 @@ typedef struct kmem_cache LinuxKMemCache;
#endif
+/*!
+ *******************************************************************************
+ * @Function LinuxMMInit
+ *
+ * @Description
+ *
+ * Initialise linux memory management code.
+ * This should be called during services initialisation.
+ *
+ * @Return none
+******************************************************************************/
PVRSRV_ERROR LinuxMMInit(IMG_VOID);
+/*!
+ *******************************************************************************
+ *
+ * @Function LinuxMMCleanup
+ *
+ * @Description
+ *
+ * Cleanup state for the linux memory management code.
+ * This should be called at services cleanup.
+ *
+ * @Return none
+******************************************************************************/
IMG_VOID LinuxMMCleanup(IMG_VOID);
+/*!
+ *******************************************************************************
+ * @brief Wrappers for kmalloc/kfree with optional /proc/pvr/km tracking
+ * They can also be used as more concise replacements for OSAllocMem
+ * in Linux specific code.
+ *
+ * @param ui32ByteSize
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KMallocWrapper(ui32ByteSize, uFlags) _KMallocWrapper(ui32ByteSize, uFlags, __FILE__, __LINE__)
#else
@@ -176,6 +256,14 @@ IMG_VOID LinuxMMCleanup(IMG_VOID);
IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *szFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param pvCpuVAddr
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KFreeWrapper(pvCpuVAddr) _KFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
#else
@@ -184,6 +272,15 @@ IMG_VOID *_KMallocWrapper(IMG_UINT32 ui32ByteSize, gfp_t uFlags, IMG_CHAR *szFil
IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Bytes
+ * @param ui32AllocFlags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define VMallocWrapper(ui32Bytes, ui32AllocFlags) _VMallocWrapper(ui32Bytes, ui32AllocFlags, __FILE__, __LINE__)
#else
@@ -192,6 +289,14 @@ IMG_VOID _KFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 u
IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param pvCpuVAddr
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define VFreeWrapper(pvCpuVAddr) _VFreeWrapper(pvCpuVAddr, __FILE__, __LINE__)
#else
@@ -200,12 +305,38 @@ IMG_VOID *_VMallocWrapper(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AllocFlags, IMG_C
IMG_VOID _VFreeWrapper(IMG_VOID *pvCpuVAddr, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief Allocates virtually contiguous pages
+ *
+ * @param ui32Bytes number of bytes to reserve
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return Page-aligned address of virtual allocation or NULL on error
+ ******************************************************************************/
LinuxMemArea *NewVMallocLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief Deallocates virtually contiguous pages
+ *
+ * @param LinuxMemArea from NewVMallocLinuxMemArea
+ *
+ ******************************************************************************/
IMG_VOID FreeVMallocLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32MappingFlags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags) \
_IORemapWrapper(BasePAddr, ui32Bytes, ui32MappingFlags, __FILE__, __LINE__)
@@ -220,17 +351,63 @@ IMG_VOID *_IORemapWrapper(IMG_CPU_PHYADDR BasePAddr,
IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief Reserve physical IO memory and create a CPU virtual mapping for it
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewIORemapLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ********************************************************************************/
IMG_VOID FreeIORemapLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief Register physical memory which already has a CPU virtual mapping
+ *
+ * @param pBasePAddr
+ * @param pvCPUVAddr
+ * @param bPhysContig
+ * @param ui32Bytes
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewExternalKVLinuxMemArea(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPUVAddr, IMG_UINT32 ui32Bytes, IMG_BOOL bPhysContig, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ ******************************************************************************
+ * @brief Unmaps an IO memory mapping created using IORemap
+ *
+ * @param pvIORemapCookie
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define IOUnmapWrapper(pvIORemapCookie) \
_IOUnmapWrapper(pvIORemapCookie, __FILE__, __LINE__)
@@ -241,15 +418,52 @@ IMG_VOID FreeExternalKVLinuxMemArea(LinuxMemArea *psLinuxMemArea);
IMG_VOID _IOUnmapWrapper(IMG_VOID *pvIORemapCookie, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ * @param ui32ByteOffset
+ *
+ * @return
+ ******************************************************************************/
struct page *LinuxMemAreaOffsetToPage(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param pszName
+ * @param Size
+ * @param Align
+ * @param ui32Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxKMemCache *KMemCacheCreateWrapper(IMG_CHAR *pszName, size_t Size, size_t Align, IMG_UINT32 ui32Flags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID KMemCacheDestroyWrapper(LinuxKMemCache *psCache);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ * @param Flags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KMemCacheAllocWrapper(psCache, Flags) _KMemCacheAllocWrapper(psCache, Flags, __FILE__, __LINE__)
#else
@@ -262,6 +476,15 @@ IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, gfp_t Flags, IMG_CHAR
IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
#endif
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ * @param pvObject
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
#define KMemCacheFreeWrapper(psCache, pvObject) _KMemCacheFreeWrapper(psCache, pvObject, __FILE__, __LINE__)
#else
@@ -270,29 +493,146 @@ IMG_VOID *_KMemCacheAllocWrapper(LinuxKMemCache *psCache, int Flags, IMG_CHAR *p
IMG_VOID _KMemCacheFreeWrapper(LinuxKMemCache *psCache, IMG_VOID *pvObject, IMG_CHAR *pszFileName, IMG_UINT32 ui32Line);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psCache
+ *
+ * @return
+ ******************************************************************************/
const IMG_CHAR *KMemCacheNameWrapper(LinuxKMemCache *psCache);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param BasePAddr
+ * @param ui32Bytes
+ * @param ui32AreaFlags Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewIOLinuxMemArea(IMG_CPU_PHYADDR BasePAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID FreeIOLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Bytes
+ * @param ui32AreaFlags E.g Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewAllocPagesLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID FreeAllocPagesLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+#if defined(CONFIG_ION_OMAP)
+
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Bytes
+ * @param ui32AreaFlags E.g Heap caching and mapping Flags
+ *
+ * @return
+ ******************************************************************************/
+LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength);
+
+
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
+IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea);
+
+#else /* defined(CONFIG_ION_OMAP) */
+
+static inline LinuxMemArea *
+NewIONLinuxMemArea(IMG_UINT32 ui32Bytes, IMG_UINT32 ui32AreaFlags,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength)
+{
+ PVR_UNREFERENCED_PARAMETER(ui32Bytes);
+ PVR_UNREFERENCED_PARAMETER(ui32AreaFlags);
+ PVR_UNREFERENCED_PARAMETER(pvPrivData);
+ PVR_UNREFERENCED_PARAMETER(ui32PrivDataLength);
+ BUG();
+ return IMG_NULL;
+}
+
+static inline IMG_VOID FreeIONLinuxMemArea(LinuxMemArea *psLinuxMemArea)
+{
+ PVR_UNREFERENCED_PARAMETER(psLinuxMemArea);
+ BUG();
+}
+
+#endif /* defined(CONFIG_ION_OMAP) */
+
+
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psParentLinuxMemArea
+ * @param ui32ByteOffset
+ * @param ui32Bytes
+ *
+ * @return
+ ******************************************************************************/
LinuxMemArea *NewSubLinuxMemArea(LinuxMemArea *psParentLinuxMemArea,
IMG_UINT32 ui32ByteOffset,
IMG_UINT32 ui32Bytes);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID LinuxMemAreaDeepFree(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief For debug builds, LinuxMemAreas are tracked in /proc
+ *
+ * @param psLinuxMemArea
+ *
+ ******************************************************************************/
#if defined(LINUX_MEM_AREAS_DEBUG)
IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
#else
@@ -300,16 +640,49 @@ IMG_VOID LinuxMemAreaRegister(LinuxMemArea *psLinuxMemArea);
#endif
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ *
+ * @return
+ ******************************************************************************/
IMG_VOID *LinuxMemAreaToCpuVAddr(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param psLinuxMemArea
+ * @param ui32ByteOffset
+ *
+ * @return
+ ******************************************************************************/
IMG_CPU_PHYADDR LinuxMemAreaToCpuPAddr(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32ByteOffset);
#define LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) PHYS_TO_PFN(LinuxMemAreaToCpuPAddr(psLinuxMemArea, ui32ByteOffset).uiAddr)
+/*!
+ *******************************************************************************
+ * @brief Indicate whether a LinuxMemArea is physically contiguous
+ *
+ * @param psLinuxMemArea
+ *
+ * @return IMG_TRUE if the physical address range is contiguous, else IMG_FALSE
+ ******************************************************************************/
IMG_BOOL LinuxMemAreaPhysIsContig(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @brief Return the real underlying LinuxMemArea
+ *
+ * @param psLinuxMemArea
+ *
+ * @return The real underlying LinuxMemArea
+ ******************************************************************************/
static inline LinuxMemArea *
LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
{
@@ -324,6 +697,14 @@ LinuxMemAreaRoot(LinuxMemArea *psLinuxMemArea)
}
+/*!
+ *******************************************************************************
+ * @brief Return type of real underlying LinuxMemArea
+ *
+ * @param psLinuxMemArea
+ *
+ * @return The areas eAreaType or for SUB areas; return the parents eAreaType.
+ ******************************************************************************/
static inline LINUX_MEM_AREA_TYPE
LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
{
@@ -331,12 +712,28 @@ LinuxMemAreaRootType(LinuxMemArea *psLinuxMemArea)
}
+/*!
+ *******************************************************************************
+ * @brief Converts the enum type of a LinuxMemArea to a const string
+ *
+ * @param eMemAreaType
+ *
+ * @return const string representation of type
+ ******************************************************************************/
const IMG_CHAR *LinuxMemAreaTypeToString(LINUX_MEM_AREA_TYPE eMemAreaType);
+/*!
+ *******************************************************************************
+ * @brief
+ *
+ * @param ui32Flags
+ *
+ * @return
+ ******************************************************************************/
#if defined(DEBUG_LINUX_MEM_AREAS) || defined(DEBUG_LINUX_MMAP_AREAS)
const IMG_CHAR *HAPFlagsToString(IMG_UINT32 ui32Flags);
#endif
-#endif
+#endif /* __IMG_LINUX_MM_H__ */
diff --git a/sgx/services4/srvkm/env/linux/mmap.c b/sgx/services4/srvkm/env/linux/mmap.c
index ca38e5d..6e032dc 100644
--- a/sgx/services4/srvkm/env/linux/mmap.c
+++ b/sgx/services4/srvkm/env/linux/mmap.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mmap interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -39,6 +55,9 @@
#include <linux/wrapper.h>
#endif
#include <linux/slab.h>
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+#include <linux/highmem.h>
+#endif
#include <asm/io.h>
#include <asm/page.h>
#include <asm/shmparam.h>
@@ -51,15 +70,12 @@
#include <drm/drmP.h>
#endif
-#include "img_defs.h"
-#include "services.h"
-#include "servicesint.h"
+#include "services_headers.h"
+
#include "pvrmmap.h"
#include "mutils.h"
#include "mmap.h"
#include "mm.h"
-#include "pvr_debug.h"
-#include "osfunc.h"
#include "proc.h"
#include "mutex.h"
#include "handle.h"
@@ -74,7 +90,19 @@
#error "The mmap code requires PVR_SECURE_HANDLES"
#endif
-static PVRSRV_LINUX_MUTEX g_sMMapMutex;
+/* WARNING:
+ * The mmap code has its own mutex, to prevent a possible deadlock,
+ * when using gPVRSRVLock.
+ * The Linux kernel takes the mm->mmap_sem before calling the mmap
+ * entry points (PVRMMap, MMapVOpen, MMapVClose), but the ioctl
+ * entry point may take mm->mmap_sem during fault handling, or
+ * before calling get_user_pages. If gPVRSRVLock was used in the
+ * mmap entry points, a deadlock could result, due to the ioctl
+ * and mmap code taking the two locks in different orders.
+ * As a corollary to this, the mmap entry points must not call
+ * any driver code that relies on gPVRSRVLock is held.
+ */
+PVRSRV_LINUX_MUTEX g_sMMapMutex;
static LinuxKMemCache *g_psMemmapCache = NULL;
static LIST_HEAD(g_sMMapAreaList);
@@ -88,9 +116,28 @@ static inline PKV_OFFSET_STRUCT FindOffsetStructByPID(LinuxMemArea *psLinuxMemAr
#if defined(DEBUG_LINUX_MMAP_AREAS)
static struct proc_dir_entry *g_ProcMMap;
-#endif
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Now that we are using mmap2 in srvclient, almost (*) the full 32
+ * bit offset is available. The range of values is divided into two.
+ * The first part of the range, from FIRST_PHYSICAL_PFN to
+ * LAST_PHYSICAL_PFN, is for raw page mappings (VM_PFNMAP). The
+ * resulting 43 bit (*) physical address range should be enough for
+ * the current range of processors we support.
+ *
+ * NB: (*) -- the above figures assume 4KB page size. The offset
+ * argument to mmap2() is in units of 4,096 bytes regardless of page
+ * size. Thus, we lose (PAGE_SHIFT-12) bits of resolution on other
+ * architectures.
+ *
+ * The second part of the range, from FIRST_SPECIAL_PFN to LAST_SPECIAL_PFN,
+ * is used for all other mappings. These other mappings will always
+ * consist of pages with associated page structures, and need not
+ * represent a contiguous range of physical addresses.
+ *
+ */
#define MMAP2_PGOFF_RESOLUTION (32-PAGE_SHIFT+12)
#define RESERVED_PGOFF_BITS 1
#define MAX_MMAP_HANDLE ((1UL<<(MMAP2_PGOFF_RESOLUTION-RESERVED_PGOFF_BITS))-1)
@@ -100,12 +147,19 @@ static struct proc_dir_entry *g_ProcMMap;
#define FIRST_SPECIAL_PFN (LAST_PHYSICAL_PFN + 1)
#define LAST_SPECIAL_PFN (FIRST_SPECIAL_PFN + MAX_MMAP_HANDLE)
-#else
+#else /* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */
#if PAGE_SHIFT != 12
#error This build variant has not yet been made non-4KB page-size aware
#endif
+/*
+ * Since we no longer have to worry about clashes with the mmap
+ * offsets used for pure PFN mappings (VM_PFNMAP), there is greater
+ * freedom in choosing the mmap handles. This is useful if the
+ * mmap offset space has to be shared with another driver component.
+ */
+
#if defined(PVR_MMAP_OFFSET_BASE)
#define FIRST_SPECIAL_PFN PVR_MMAP_OFFSET_BASE
#else
@@ -118,21 +172,21 @@ static struct proc_dir_entry *g_ProcMMap;
#define MAX_MMAP_HANDLE 0x7fffffffUL
#endif
-#endif
+#endif /* !defined(PVR_MAKE_ALL_PFNS_SPECIAL) */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
static inline IMG_BOOL
PFNIsPhysical(IMG_UINT32 pfn)
{
-
- return ( (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
+ /* Unsigned, no need to compare >=0 */
+ return (/*(pfn >= FIRST_PHYSICAL_PFN) &&*/ (pfn <= LAST_PHYSICAL_PFN)) ? IMG_TRUE : IMG_FALSE;
}
static inline IMG_BOOL
PFNIsSpecial(IMG_UINT32 pfn)
{
-
- return ((pfn >= FIRST_SPECIAL_PFN) ) ? IMG_TRUE : IMG_FALSE;
+ /* Unsigned, no need to compare <=MAX_UINT */
+ return ((pfn >= FIRST_SPECIAL_PFN) /*&& (pfn <= LAST_SPECIAL_PFN)*/) ? IMG_TRUE : IMG_FALSE;
}
#endif
@@ -169,6 +223,16 @@ HandleToMMapOffset(IMG_HANDLE hHandle)
}
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
+/*
+ * Determine whether physical or special mappings will be used for
+ * a given memory area. At present, this decision is made on
+ * whether the mapping represents a contiguous range of physical
+ * addresses, which is a requirement for raw page mappings (VM_PFNMAP).
+ * In the VMA structure for such a mapping, vm_pgoff is the PFN
+ * (page frame number, the physical address divided by the page size)
+ * of the first page in the VMA. The second page is assumed to have
+ * PFN (vm_pgoff + 1), the third (vm_pgoff + 2) and so on.
+ */
static inline IMG_BOOL
LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
{
@@ -180,11 +244,18 @@ LinuxMemAreaUsesPhysicalMap(LinuxMemArea *psLinuxMemArea)
static inline IMG_UINT32
GetCurrentThreadID(IMG_VOID)
{
-
+ /*
+ * The PID is the thread ID, as each thread is a
+ * seperate process.
+ */
return (IMG_UINT32)current->pid;
}
#endif
+/*
+ * Create an offset structure, which is used to hold per-process
+ * mmap data.
+ */
static PKV_OFFSET_STRUCT
CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
{
@@ -216,14 +287,22 @@ CreateOffsetStruct(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32Offset, IMG_UINT
psOffsetStruct->ui32RealByteSize = ui32RealByteSize;
-
+ /*
+ * We store the TID in case two threads within a process
+ * generate the same offset structure, and both end up on the
+ * list of structures waiting to be mapped, at the same time.
+ * This could happen if two sub areas within the same page are
+ * being mapped at the same time.
+ * The TID allows the mmap entry point to distinguish which
+ * mapping is being done by which thread.
+ */
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
psOffsetStruct->ui32TID = GetCurrentThreadID();
#endif
psOffsetStruct->ui32PID = OSGetCurrentProcessIDKM();
#if defined(DEBUG_LINUX_MMAP_AREAS)
-
+ /* Extra entries to support proc filesystem debug info */
psOffsetStruct->pszName = pszName;
#endif
@@ -259,6 +338,17 @@ DestroyOffsetStruct(PKV_OFFSET_STRUCT psOffsetStruct)
}
+/*
+ * There are no alignment constraints for mapping requests made by user
+ * mode Services. For this, and potentially other reasons, the
+ * mapping created for a users request may look different to the
+ * original request in terms of size and alignment.
+ *
+ * This function determines an offset that the user can add to the mapping
+ * that is _actually_ created which will point to the memory they are
+ * _really_ interested in.
+ *
+ */
static inline IMG_VOID
DetermineUsersSizeAndByteOffset(LinuxMemArea *psLinuxMemArea,
IMG_UINT32 *pui32RealByteSize,
@@ -337,7 +427,7 @@ create_gem_wrapper(struct drm_device *dev, LinuxMemArea *psLinuxMemArea,
case LINUX_MEM_AREA_ALLOC_PAGES:
pages = kmalloc(sizeof(pages) * npages, GFP_KERNEL);
for (i = 0; i < npages; i++) {
- pages[i] = psLinuxMemArea->uData.sPageList.pvPageList[i + PHYS_TO_PFN(ui32ByteOffset)];
+ pages[i] = psLinuxMemArea->uData.sPageList.ppsPageList[i + PHYS_TO_PFN(ui32ByteOffset)];
}
break;
case LINUX_MEM_AREA_SUB_ALLOC:
@@ -355,7 +445,6 @@ create_gem_wrapper(struct drm_device *dev, LinuxMemArea *psLinuxMemArea,
/* map PVR cache type flags to GEM.. */
switch(psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK) {
case PVRSRV_HAP_CACHED:
- case PVRSRV_HAP_SMART:
flags = OMAP_BO_CACHED;
break;
case PVRSRV_HAP_WRITECOMBINE:
@@ -380,6 +469,33 @@ create_gem_wrapper(struct drm_device *dev, LinuxMemArea *psLinuxMemArea,
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapOSMemHandleToMMapData
+
+ @Description
+
+ Determine various parameters needed to mmap a memory area, and to
+ locate the memory within the mapped area.
+
+ @input psPerProc : Per-process data.
+ @input hMHandle : Memory handle.
+ @input pui32MMapOffset : pointer to location for returned mmap offset.
+ @input pui32ByteOffset : pointer to location for returned byte offset.
+ @input pui32RealByteSize : pointer to location for returned real byte size.
+ @input pui32UserVaddr : pointer to location for returned user mode address.
+
+ @output pui32MMapOffset : points to mmap offset to be used in mmap2 sys call.
+ @output pui32ByteOffset : points to byte offset of start of memory
+ within mapped area returned by mmap2.
+ @output pui32RealByteSize : points to size of area to be mapped.
+ @output pui32UserVAddr : points to user mode address of start of
+ mapping, or 0 if it hasn't been mapped yet.
+
+ @Return PVRSRV_ERROR : PVRSRV_OK, or error code.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
@@ -442,24 +558,43 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
}
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
- DetermineUsersSizeAndByteOffset(psLinuxMemArea,
- pui32RealByteSize,
- pui32ByteOffset);
+ /* Sparse mappings have to ask the BM for the virtual size */
+ if (psLinuxMemArea->hBMHandle)
+ {
+ *pui32RealByteSize = BM_GetVirtualSize(psLinuxMemArea->hBMHandle);
+ *pui32ByteOffset = 0;
+ }
+ else
+ {
+ DetermineUsersSizeAndByteOffset(psLinuxMemArea,
+ pui32RealByteSize,
+ pui32ByteOffset);
+ }
psOffsetStruct = FindOffsetStructByPID(psLinuxMemArea, psPerProc->ui32PID);
if (psOffsetStruct)
{
- PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
-
+ if (!psLinuxMemArea->hBMHandle)
+ {
+ PVR_ASSERT(*pui32RealByteSize == psOffsetStruct->ui32RealByteSize);
+ }
+ /*
+ * User mode locking is required to stop two threads racing to
+ * map the same memory area. The lock should prevent a
+ * second thread retrieving mmap data for a given handle,
+ * before the first thread has done the mmap.
+ * Without locking, both threads may attempt the mmap,
+ * and one of them will fail.
+ */
*pui32MMapOffset = psOffsetStruct->ui32MMapOffset;
*pui32UserVAddr = psOffsetStruct->ui32UserVAddr;
- psOffsetStruct->ui32RefCount++;
+ PVRSRVOffsetStructIncRef(psOffsetStruct);
eError = PVRSRV_OK;
goto exit_unlock;
}
-
+ /* Memory area won't have been mapped yet */
*pui32UserVAddr = 0;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
@@ -495,18 +630,22 @@ PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
goto exit_unlock;
}
-
+ /*
+ * Offset structures representing physical mappings are added to
+ * a list, so that they can be located when the memory area is mapped.
+ */
list_add_tail(&psOffsetStruct->sMMapItem, &g_sMMapOffsetStructList);
psOffsetStruct->bOnMMapList = IMG_TRUE;
- psOffsetStruct->ui32RefCount++;
+ PVRSRVOffsetStructIncRef(psOffsetStruct);
eError = PVRSRV_OK;
-
-
-
+ /* Need to scale up the offset to counter the shifting that
+ is done in the mmap2() syscall, as it expects the pgoff
+ argument to be in units of 4,096 bytes irrespective of
+ page size */
*pui32MMapOffset = *pui32MMapOffset << (PAGE_SHIFT - 12);
exit_unlock:
@@ -517,6 +656,28 @@ exit_unlock:
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapReleaseMMapData
+
+ @Description
+
+ Release mmap data.
+
+ @input psPerProc : Per-process data.
+ @input hMHandle : Memory handle.
+ @input pbMUnmap : pointer to location for munmap flag.
+ @input pui32UserVAddr : pointer to location for user mode address of mapping.
+ @input pui32ByteSize : pointer to location for size of mapping.
+
+ @Output pbMUnmap : points to flag that indicates whether an munmap is
+ required.
+ @output pui32UserVAddr : points to user mode address to munmap.
+
+ @Return PVRSRV_ERROR : PVRSRV_OK, or error code.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
@@ -562,7 +723,7 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
goto exit_unlock;
}
- psOffsetStruct->ui32RefCount--;
+ PVRSRVOffsetStructDecRef(psOffsetStruct);
*pbMUnmap = (IMG_BOOL)((psOffsetStruct->ui32RefCount == 0) && (psOffsetStruct->ui32UserVAddr != 0));
@@ -573,7 +734,7 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
goto exit_unlock;
}
-
+ /* MMap data not found */
#if defined (SUPPORT_SID_INTERFACE)
PVR_DPF((PVR_DBG_ERROR, "%s: Mapping data not found for handle %x (memory area %p)", __FUNCTION__, hMHandle, psLinuxMemArea));
#else
@@ -602,7 +763,11 @@ FindOffsetStructByOffset(IMG_UINT32 ui32Offset, IMG_UINT32 ui32RealByteSize)
if (ui32Offset == psOffsetStruct->ui32MMapOffset && ui32RealByteSize == psOffsetStruct->ui32RealByteSize && psOffsetStruct->ui32PID == ui32PID)
{
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
-
+ /*
+ * If the offset is physical, make sure the thread IDs match,
+ * as different threads may be mapping different memory areas
+ * with the same offset.
+ */
if (!PFNIsPhysical(ui32Offset) || psOffsetStruct->ui32TID == ui32TID)
#endif
{
@@ -627,7 +792,11 @@ FindOffsetStructByPID(LinuxMemArea *psLinuxMemArea, IMG_UINT32 ui32PID)
}
return NULL;
}
-
+/*
+ * Map a memory area into user space.
+ * Note, the ui32ByteOffset is _not_ implicitly page aligned since
+ * LINUX_MEM_AREA_SUB_ALLOC LinuxMemAreas have no alignment constraints.
+ */
static IMG_BOOL
DoMapToUser(LinuxMemArea *psLinuxMemArea,
struct vm_area_struct* ps_vma,
@@ -635,19 +804,33 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
{
IMG_UINT32 ui32ByteSize;
+ if ((psLinuxMemArea->hBMHandle) && (ui32ByteOffset != 0))
+ {
+ /* Partial mapping of sparse allocations should never happen */
+ return IMG_FALSE;
+ }
+
if (psLinuxMemArea->eAreaType == LINUX_MEM_AREA_SUB_ALLOC)
{
- return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea),
+ return DoMapToUser(LinuxMemAreaRoot(psLinuxMemArea), /* PRQA S 3670 */ /* allow recursion */
ps_vma,
psLinuxMemArea->uData.sSubAlloc.ui32ByteOffset + ui32ByteOffset);
}
-
+ /*
+ * Note that ui32ByteSize may be larger than the size of the memory
+ * area being mapped, as the former is a multiple of the page size.
+ */
ui32ByteSize = ps_vma->vm_end - ps_vma->vm_start;
PVR_ASSERT(ADDR_TO_PAGE_OFFSET(ui32ByteSize) == 0);
#if defined (__sparc__)
-
+ /*
+ * For LINUX_MEM_AREA_EXTERNAL_KV, we don't know where the address range
+ * we are being asked to map has come from, that is, whether it is memory
+ * or I/O. For all architectures other than SPARC, there is no distinction.
+ * Since we don't currently support SPARC, we won't worry about it.
+ */
#error "SPARC not supported"
#endif
@@ -658,7 +841,13 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
PVR_ASSERT(LinuxMemAreaPhysIsContig(psLinuxMemArea));
PVR_ASSERT(LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32ByteOffset) == ps_vma->vm_pgoff);
-
+ /*
+ * Since the memory is contiguous, we can map the whole range in one
+ * go .
+ */
+
+ PVR_ASSERT(psLinuxMemArea->hBMHandle == IMG_NULL);
+
result = IO_REMAP_PFN_RANGE(ps_vma, ps_vma->vm_start, ps_vma->vm_pgoff, ui32ByteSize, ps_vma->vm_page_prot);
if(result == 0)
@@ -671,27 +860,51 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
#endif
{
-
+ /*
+ * Memory may be non-contiguous, so we map the range page,
+ * by page. Since VM_PFNMAP mappings are assumed to be physically
+ * contiguous, we can't legally use REMAP_PFN_RANGE (that is, we
+ * could, but the resulting VMA may confuse other bits of the kernel
+ * that attempt to interpret it).
+ * The only alternative is to use VM_INSERT_PAGE, which requires
+ * finding the page structure corresponding to each page, or
+ * if mixed maps are supported (VM_MIXEDMAP), vm_insert_mixed.
+ */
IMG_UINT32 ulVMAPos;
IMG_UINT32 ui32ByteEnd = ui32ByteOffset + ui32ByteSize;
IMG_UINT32 ui32PA;
+ IMG_UINT32 ui32AdjustedPA = ui32ByteOffset;
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
IMG_BOOL bMixedMap = IMG_FALSE;
#endif
-
+ /* First pass, validate the page frame numbers */
for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
{
- IMG_UINT32 pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ IMG_UINT32 pfn;
+ IMG_BOOL bMapPage = IMG_TRUE;
- if (!pfn_valid(pfn))
- {
+ if (psLinuxMemArea->hBMHandle)
+ {
+ if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA))
+ {
+ bMapPage = IMG_FALSE;
+ }
+ }
+
+ if (bMapPage)
+ {
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA);
+ if (!pfn_valid(pfn))
+ {
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
- return IMG_FALSE;
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - PFN invalid: 0x%x", __FUNCTION__, pfn));
+ return IMG_FALSE;
#else
- bMixedMap = IMG_TRUE;
+ bMixedMap = IMG_TRUE;
#endif
- }
+ }
+ ui32AdjustedPA += PAGE_SIZE;
+ }
}
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
@@ -700,43 +913,58 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
ps_vma->vm_flags |= VM_MIXEDMAP;
}
#endif
-
+ /* Second pass, get the page structures and insert the pages */
ulVMAPos = ps_vma->vm_start;
+ ui32AdjustedPA = ui32ByteOffset;
for(ui32PA = ui32ByteOffset; ui32PA < ui32ByteEnd; ui32PA += PAGE_SIZE)
{
IMG_UINT32 pfn;
IMG_INT result;
+ IMG_BOOL bMapPage = IMG_TRUE;
+
+ if (psLinuxMemArea->hBMHandle)
+ {
+ /* We have a sparse allocation, check if this page should be mapped */
+ if (!BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32PA))
+ {
+ bMapPage = IMG_FALSE;
+ }
+ }
- pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32PA);
+ if (bMapPage)
+ {
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ui32AdjustedPA);
#if defined(PVR_MAKE_ALL_PFNS_SPECIAL)
- if (bMixedMap)
- {
- result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
- if(result != 0)
- {
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
- return IMG_FALSE;
- }
- }
- else
+ if (bMixedMap)
+ {
+ result = vm_insert_mixed(ps_vma, ulVMAPos, pfn);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - vm_insert_mixed failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ else
#endif
- {
- struct page *psPage;
-
- PVR_ASSERT(pfn_valid(pfn));
-
- psPage = pfn_to_page(pfn);
-
- result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
- if(result != 0)
- {
- PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
- return IMG_FALSE;
- }
- }
- ulVMAPos += PAGE_SIZE;
- }
+ {
+ struct page *psPage;
+
+ PVR_ASSERT(pfn_valid(pfn));
+
+ psPage = pfn_to_page(pfn);
+
+ result = VM_INSERT_PAGE(ps_vma, ulVMAPos, psPage);
+ if(result != 0)
+ {
+ PVR_DPF((PVR_DBG_ERROR,"%s: Error - VM_INSERT_PAGE failed (%d)", __FUNCTION__, result));
+ return IMG_FALSE;
+ }
+ }
+ ui32AdjustedPA += PAGE_SIZE;
+ }
+ ulVMAPos += PAGE_SIZE;
+ }
}
return IMG_TRUE;
@@ -746,10 +974,11 @@ DoMapToUser(LinuxMemArea *psLinuxMemArea,
static IMG_VOID
MMapVOpenNoLock(struct vm_area_struct* ps_vma, PKV_OFFSET_STRUCT psOffsetStruct)
{
- PVR_ASSERT(psOffsetStruct != IMG_NULL)
- psOffsetStruct->ui32Mapped++;
+ PVR_ASSERT(psOffsetStruct != IMG_NULL);
PVR_ASSERT(!psOffsetStruct->bOnMMapList);
+ PVRSRVOffsetStructIncMapped(psOffsetStruct);
+
if (psOffsetStruct->ui32Mapped > 1)
{
PVR_DPF((PVR_DBG_WARNING, "%s: Offset structure 0x%p is being shared across processes (psOffsetStruct->ui32Mapped: %u)", __FUNCTION__, psOffsetStruct, psOffsetStruct->ui32Mapped));
@@ -769,6 +998,9 @@ MMapVOpenNoLock(struct vm_area_struct* ps_vma, PKV_OFFSET_STRUCT psOffsetStruct)
}
+/*
+ * Linux mmap open entry point.
+ */
static void
MMapVOpen(struct vm_area_struct* ps_vma)
{
@@ -799,7 +1031,7 @@ MMapVCloseNoLock(struct vm_area_struct* ps_vma, PKV_OFFSET_STRUCT psOffsetStruct
#endif
PVR_ASSERT(!psOffsetStruct->bOnMMapList);
- psOffsetStruct->ui32Mapped--;
+ PVRSRVOffsetStructDecMapped(psOffsetStruct);
if (psOffsetStruct->ui32Mapped == 0)
{
if (psOffsetStruct->ui32RefCount != 0)
@@ -813,6 +1045,9 @@ MMapVCloseNoLock(struct vm_area_struct* ps_vma, PKV_OFFSET_STRUCT psOffsetStruct
ps_vma->vm_private_data = NULL;
}
+/*
+ * Linux mmap close entry point.
+ */
static void
MMapVClose(struct vm_area_struct* ps_vma)
{
@@ -823,361 +1058,103 @@ MMapVClose(struct vm_area_struct* ps_vma)
LinuxUnLockMutex(&g_sMMapMutex);
}
-
-static struct vm_operations_struct MMapIOOps =
-{
- .open=MMapVOpen,
- .close=MMapVClose
-};
-
-/*****************************************************************************/
-/* "Smart" cached buffer support..
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+/*
+ * This vma operation is used to read data from mmap regions. It is called
+ * by access_process_vm, which is called to handle PTRACE_PEEKDATA ptrace
+ * requests and reads from /proc/<pid>/mem.
*/
-
-#include <linux/rmap.h>
-#include <linux/pagemap.h>
-
-typedef struct {
- struct mutex lock; /* mutex that protects the page list */
- struct list_head faulted; /* list of touched pages */
- int npages; /* number of pages in buffer */
- struct vm_area_struct *vma; /* vma of initial creator of buffer */
-} PVRMMapSmartCache;
-
-enum {
- PG_touched = PG_private,
- PG_written = PG_private_2
-};
-
-static IMG_VOID PVRMMapUnmapInv(IMG_HANDLE hSmartCache, bool inv);
-
-
-#ifndef DBG
-#define DBG(fmt, ...) do {} while (0)
-//#define DBG(fmt, ...) printk(KERN_INFO"[%s:%d] "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-#ifndef VERB
-#define VERB(fmt, ...) do {} while (0)
-//#define VERB(fmt, ...) printk(KERN_INFO"[%s:%d] "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-#endif
-#define ERR(fmt, ...) printk(KERN_ERR"ERR: [%s:%d] "fmt"\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
-
-static int
-MMapVFault(struct vm_area_struct *vma, struct vm_fault *vmf)
+static int MMapVAccess(struct vm_area_struct *ps_vma, unsigned long addr,
+ void *buf, int len, int write)
{
- PKV_OFFSET_STRUCT psOffsetStruct = vma->vm_private_data;
- LinuxMemArea *psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
- PVRMMapSmartCache *smart = psLinuxMemArea->hSmartCache;
- unsigned long offset, pfn;
- struct page *page;
- pgoff_t pgoff;
- int ret = VM_FAULT_NOPAGE;
-
- if (!smart)
- {
- ERR("uhh oh, I'm not smart..\n");
- return VM_FAULT_SIGBUS;
- }
-
- /* We don't use vmf->pgoff since that has the fake offset */
- pgoff = ((unsigned long)vmf->virtual_address - vma->vm_start) >> PAGE_SHIFT;
- offset = pgoff << PAGE_SHIFT;
- if (offset >= psOffsetStruct->psLinuxMemArea->ui32ByteSize)
- {
- ERR("%p: offset too big: %lu vs %u, %p", smart, offset,
- psOffsetStruct->psLinuxMemArea->ui32ByteSize,
- psOffsetStruct->psLinuxMemArea);
- return VM_FAULT_SIGBUS;
- }
-
- pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, offset);
- page = pfn_to_page(pfn);
- if (!page)
- {
- ERR("%p: can't find page: %lu, %p", smart, offset, psLinuxMemArea);
- return VM_FAULT_SIGBUS;
- }
-
+ PKV_OFFSET_STRUCT psOffsetStruct;
+ LinuxMemArea *psLinuxMemArea;
+ unsigned long ulOffset;
+ int iRetVal = -EINVAL;
+ IMG_VOID *pvKernelAddr;
- /* *** BEGIN CRITICAL SECTION ********************************************/
- mutex_lock(&smart->lock);
+ LinuxLockMutex(&g_sMMapMutex);
- /* if we already know of this page the we are done */
- if (test_and_set_bit(PG_touched, &page->flags))
- {
- VERB("%p: (already touched) get_page(%p) (idx=%08lx, flg=%08x, cnt=%d)",
- smart, page, page->index, vmf->flags, atomic_read(&page->_count));
- goto unlock;
- }
+ psOffsetStruct = (PKV_OFFSET_STRUCT)ps_vma->vm_private_data;
+ psLinuxMemArea = psOffsetStruct->psLinuxMemArea;
+ ulOffset = addr - ps_vma->vm_start;
- page->index = pgoff + vma->vm_pgoff;
+ if (ulOffset+len > psLinuxMemArea->ui32ByteSize)
+ /* Out of range. We shouldn't get here, because the kernel will do
+ the necessary checks before calling access_process_vm. */
+ goto exit_unlock;
- VERB("%p: get_page(%p) (idx=%08lx, flg=%08x, cnt=%d)",
- smart, page, page->index, vmf->flags, atomic_read(&page->_count));
+ pvKernelAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
- if (vma->vm_file)
+ if (pvKernelAddr)
{
- page->mapping = vma->vm_file->f_mapping;
+ memcpy(buf, pvKernelAddr+ulOffset, len);
+ iRetVal = len;
}
else
{
- ERR("%p: no mapping available\n", smart);
- }
+ IMG_UINT32 pfn, ui32OffsetInPage;
+ struct page *page;
- BUG_ON(!page->mapping);
+ pfn = LinuxMemAreaToCpuPFN(psLinuxMemArea, ulOffset);
- vmf->page = page;
+ if (!pfn_valid(pfn))
+ goto exit_unlock;
- get_page(page);
- ret = vm_insert_mixed(vma, (unsigned long)vmf->virtual_address, pfn);
- if (ret)
- {
- ERR("%p: error inserting page: %d", smart, ret);
- goto unlock;
- }
- ret = VM_FAULT_NOPAGE;
-
- /* Add the page to the list of pages that have been touched
- */
- list_add_tail(&page->lru, &smart->faulted);
-
-unlock:
- mutex_unlock(&smart->lock);
- /* *** END CRITICAL SECTION **********************************************/
-
- return ret;
-}
-
-static int
-MMapVMkWrite(struct vm_area_struct *vma, struct vm_fault *vmf)
-{
- PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)vma->vm_private_data;
- PVRMMapSmartCache *smart = psOffsetStruct->psLinuxMemArea->hSmartCache;
- struct page *page = vmf->page;
-
- VERB("%p: page=%p", smart, page);
-
- /* *** BEGIN CRITICAL SECTION ********************************************/
- mutex_lock(&smart->lock);
-
- /* We want the page to remain locked from ->page_mkwrite until
- * the PTE is marked dirty to avoid page_mkclean() being called
- * before the PTE is updated, which would leave the page ignored.
- *
- * Do this by locking the page here and informing the caller
- * about it with VM_FAULT_LOCKED.
- */
- lock_page(page);
+ page = pfn_to_page(pfn);
+ ui32OffsetInPage = ADDR_TO_PAGE_OFFSET(ulOffset);
- set_bit(PG_written, &page->flags);
+ if (ui32OffsetInPage+len > PAGE_SIZE)
+ /* The region crosses a page boundary */
+ goto exit_unlock;
- mutex_unlock(&smart->lock);
- /* *** END CRITICAL SECTION **********************************************/
+ pvKernelAddr = kmap(page);
+ memcpy(buf, pvKernelAddr+ui32OffsetInPage, len);
+ kunmap(page);
- return VM_FAULT_LOCKED;
-}
-
-static void
-MMapVClose2(struct vm_area_struct* vma)
-{
- PKV_OFFSET_STRUCT psOffsetStruct = (PKV_OFFSET_STRUCT)vma->vm_private_data;
- PVRMMapSmartCache *smart = psOffsetStruct->psLinuxMemArea->hSmartCache;
- DBG("%p", smart);
- PVRMMapUnmapInv(smart, false);
- MMapVClose(vma);
-}
-
-static struct vm_operations_struct MMapSmartOps = {
- .open=MMapVOpen,
- .close=MMapVClose2,
- .fault=MMapVFault,
- .page_mkwrite=MMapVMkWrite,
-};
-
-static int
-MMapSetPageDirty(struct page *page)
-{
- if (!PageDirty(page))
- SetPageDirty(page);
- return 0;
-}
-
-static const struct address_space_operations MMapSmartAOps = {
- .set_page_dirty = MMapSetPageDirty,
-};
-
-/* prepare buffer transition CPU -> GPU */
-IMG_VOID
-PVRMMapPrepareCpuToGpu(IMG_HANDLE hSmartCache)
-{
-#if 0
- PVRMMapSmartCache *smart = hSmartCache;
- struct page *page;
- int cnt = 0;
-
- /* hopefully this is the common-path.. */
- if (list_empty(&smart->faulted))
- {
- return;
+ iRetVal = len;
}
- /* *** BEGIN CRITICAL SECTION ********************************************/
- mutex_lock(&smart->lock);
-
- list_for_each_entry(page, &smart->faulted, lru) {
- if (test_and_clear_bit(PG_written, &page->flags))
- {
- void *va = (void *)(smart->vma->vm_start +
- ((page->index - smart->vma->vm_pgoff) << PAGE_SHIFT));
- unsigned long pa = page_to_phys(page);
-
- lock_page(page);
- page_mkclean(page);
- dmac_clean_range(va, va + PAGE_SIZE);
- outer_clean_range(pa, pa + PAGE_SIZE);
- unlock_page(page);
-
- cnt++;
- }
- }
-
- mutex_unlock(&smart->lock);
- /* *** END CRITICAL SECTION **********************************************/
-
- DBG("%p: cleaned %d (of %d)", smart, cnt, smart->npages);
-#else
- PVRMMapUnmapInv(hSmartCache, true);
-#endif
-}
-/* prepare buffer transition GPU -> CPU */
-IMG_VOID
-PVRMMapPrepareGpuToCpu(IMG_HANDLE hSmartCache)
-{
- PVRMMapUnmapInv(hSmartCache, true);
+exit_unlock:
+ LinuxUnLockMutex(&g_sMMapMutex);
+ return iRetVal;
}
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) */
-/* remove faulted pages from user's vm, and optionally invalidate.. */
-static IMG_VOID
-PVRMMapUnmapInv(IMG_HANDLE hSmartCache, bool inv)
+static struct vm_operations_struct MMapIOOps =
{
- PVRMMapSmartCache *smart = hSmartCache;
- struct page *page, *next;
- pgoff_t min = ULONG_MAX, max = 0;
- struct address_space *mapping = NULL;
- int cnt = 0;
-
- /* hopefully this is the common-path.. */
- if (list_empty(&smart->faulted))
- {
- return;
- }
-
- VERB("%p", smart);
-
- /* *** BEGIN CRITICAL SECTION ********************************************/
- mutex_lock(&smart->lock);
-
- list_for_each_entry(page, &smart->faulted, lru) {
-
- if (inv)
- {
- void *va = (void *)(smart->vma->vm_start +
- ((page->index - smart->vma->vm_pgoff) << PAGE_SHIFT));
-
-#if 0
- dmac_inv_range(va, va + PAGE_SIZE);
-#else
- dmac_flush_range(va, va + PAGE_SIZE);
-#endif
- }
-
- clear_bit(PG_touched, &page->flags);
- clear_bit(PG_written, &page->flags);
-
- min = min(min, page->index);
- max = max(max, page->index);
-
- mapping = page->mapping;
-
- cnt++;
- }
-
- /* clear out the mapping that we setup.. do this before
- * invalidating to avoid a window where the cache is
- * clean, but access to it is not protected by a fault
- */
- if (mapping)
- {
- VERB("unmap_mapping_range: max=%08lx, min=%08lx", max, min);
- unmap_mapping_range(mapping, min << PAGE_SHIFT,
- (max - min + 1) << PAGE_SHIFT, 1);
- }
-
- list_for_each_entry_safe(page, next, &smart->faulted, lru) {
-
- if (inv)
- {
- unsigned long pa = page_to_phys(page);
-
-#if 0
- outer_inv_range(pa, pa + PAGE_SIZE);
-#else
- outer_flush_range(pa, pa + PAGE_SIZE);
+ .open=MMapVOpen,
+ .close=MMapVClose,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26))
+ .access=MMapVAccess,
#endif
- }
-
- VERB("%p: put_page(%p) (idx=%08lx, cnt=%d)",
- smart, page, page->index, atomic_read(&page->_count));
-
- page->index = 0;
- page->mapping = NULL;
-
- put_page(page);
-
- list_del(&page->lru);
- }
-
- mutex_unlock(&smart->lock);
- /* *** END CRITICAL SECTION **********************************************/
-
- DBG("%p: put %d (of %d)", smart, cnt, smart->npages);
-}
-
-/* setup smart cache buffer */
-IMG_HANDLE
-PVRMMapAllocateSmart(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo)
-{
- PVRMMapSmartCache *smart = kzalloc(sizeof(*smart), GFP_KERNEL);
-
- DBG("%p", smart);
+};
- mutex_init(&smart->lock);
- INIT_LIST_HEAD(&smart->faulted);
- return smart;
-}
+/*!
+ *******************************************************************************
-IMG_VOID
-PVRMMapFreeSmart(IMG_HANDLE hSmartCache)
-{
- PVRMMapSmartCache *smart = hSmartCache;
+ @Function PVRMMap
- DBG("%p", smart);
+ @Description
- PVRMMapUnmapInv(smart, false);
+ Driver mmap entry point.
- mutex_destroy(&smart->lock);
+ @input pFile : unused.
+ @input ps_vma : pointer to linux memory area descriptor.
- kfree(smart);
-}
-/*****************************************************************************/
+ @Return 0, or Linux error code.
+ ******************************************************************************/
int
PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
{
- IMG_UINT32 ui32ByteSize;
+ LinuxMemArea *psFlushMemArea = IMG_NULL;
PKV_OFFSET_STRUCT psOffsetStruct;
+ IMG_UINT32 ui32ByteSize;
+ IMG_VOID *pvBase = IMG_NULL;
int iRetVal = 0;
+ IMG_UINT32 ui32ByteOffset = 0; /* Keep compiler happy */
PVR_UNREFERENCED_PARAMETER(pFile);
@@ -1192,17 +1169,23 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
ui32ByteSize, ui32ByteSize));
psOffsetStruct = FindOffsetStructByOffset(ps_vma->vm_pgoff, ui32ByteSize);
+
if (psOffsetStruct == IMG_NULL)
{
#if defined(SUPPORT_DRI_DRM)
LinuxUnLockMutex(&g_sMMapMutex);
#if !defined(SUPPORT_DRI_DRM_EXT)
-
+ /* Pass unknown requests onto the DRM module */
return drm_mmap(pFile, ps_vma);
#else
-
- return -ENOENT;
+ /*
+ * Indicate to caller that the request is not for us.
+ * Do not return this error elsewhere in this function, as the
+ * caller may use it as a clue as to whether the mmap request
+ * should be passed on to another component (e.g. drm_mmap).
+ */
+ return -ENOENT;
#endif
#else
PVR_UNREFERENCED_PARAMETER(pFile);
@@ -1214,10 +1197,11 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
#endif
goto unlock_and_return;
}
+
list_del(&psOffsetStruct->sMMapItem);
psOffsetStruct->bOnMMapList = IMG_FALSE;
-
+ /* Only support shared writeable mappings */
if (((ps_vma->vm_flags & VM_WRITE) != 0) &&
((ps_vma->vm_flags & VM_SHARED) == 0))
{
@@ -1232,10 +1216,13 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
ps_vma->vm_flags |= VM_RESERVED;
ps_vma->vm_flags |= VM_IO;
-
+ /*
+ * Disable mremap because our nopage handler assumes all
+ * page requests have already been validated.
+ */
ps_vma->vm_flags |= VM_DONTEXPAND;
-
+ /* Don't allow mapping to be inherited across a process fork */
ps_vma->vm_flags |= VM_DONTCOPY;
ps_vma->vm_private_data = (void *)psOffsetStruct;
@@ -1243,7 +1230,7 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
switch(psOffsetStruct->psLinuxMemArea->ui32AreaFlags & PVRSRV_HAP_CACHETYPE_MASK)
{
case PVRSRV_HAP_CACHED:
- case PVRSRV_HAP_SMART:
+ /* This is the default, do nothing. */
break;
case PVRSRV_HAP_WRITECOMBINE:
ps_vma->vm_page_prot = PGPROT_WC(ps_vma->vm_page_prot);
@@ -1254,76 +1241,58 @@ PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma)
default:
PVR_DPF((PVR_DBG_ERROR, "%s: unknown cache type", __FUNCTION__));
iRetVal = -EINVAL;
- goto unlock_and_return;
+ goto unlock_and_return;
}
- if (psOffsetStruct->psLinuxMemArea->hSmartCache)
- {
- PVRMMapSmartCache *smart = psOffsetStruct->psLinuxMemArea->hSmartCache;
- DBG("using smart cache, smart=%p, psLinuxMemArea=%p (%d, %d)",
- psOffsetStruct->psLinuxMemArea->hSmartCache,
- psOffsetStruct->psLinuxMemArea,
- psOffsetStruct->ui32RealByteSize,
- psOffsetStruct->psLinuxMemArea->ui32ByteSize);
- smart->npages = (psOffsetStruct->ui32RealByteSize + PAGE_SIZE - 1) / PAGE_SIZE;
- /* abuse pgoff a bit less.. in unmap_mapping_range() it is assumed
- * that the offset is something sane, and I think it probably
- * shouldn't intersect with other page->index's.. otherwise I
- * suspect the prio_tree stuff won't work out..
- */
- ps_vma->vm_pgoff = ps_vma->vm_start >> PAGE_SHIFT;
- smart->vma = ps_vma;
- ps_vma->vm_ops = &MMapSmartOps;
- pFile->f_mapping->a_ops = &MMapSmartAOps;
-
- ps_vma->vm_flags |= VM_MIXEDMAP;
- }
- else
+ /* Install open and close handlers for ref-counting */
+ ps_vma->vm_ops = &MMapIOOps;
+
+ if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
{
- ps_vma->vm_ops = &MMapIOOps;
- if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
- {
- iRetVal = -EAGAIN;
- goto unlock_and_return;
- }
+ iRetVal = -EAGAIN;
+ goto unlock_and_return;
}
PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0);
psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
-
+ /* Compute the flush region (if necessary) inside the mmap mutex */
if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
{
- IMG_UINT32 ui32RealByteSize, ui32ByteOffset;
- IMG_VOID *pvBase;
+ IMG_UINT32 ui32DummyByteSize;
DetermineUsersSizeAndByteOffset(psOffsetStruct->psLinuxMemArea,
- &ui32RealByteSize,
+ &ui32DummyByteSize,
&ui32ByteOffset);
- ui32RealByteSize = psOffsetStruct->psLinuxMemArea->ui32ByteSize;
pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
+ psFlushMemArea = psOffsetStruct->psLinuxMemArea;
- OSInvalidateCPUCacheRangeKM(psOffsetStruct->psLinuxMemArea,
- pvBase, ui32RealByteSize);
psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
}
-
+
+ /* Call the open routine to increment the usage count */
MMapVOpenNoLock(ps_vma, ps_vma->vm_private_data);
PVR_DPF((PVR_DBG_MESSAGE, "%s: Mapped area at offset 0x%08lx\n",
__FUNCTION__, ps_vma->vm_pgoff));
-
+
unlock_and_return:
if (iRetVal != 0 && psOffsetStruct != IMG_NULL)
{
- DestroyOffsetStruct(psOffsetStruct);
+ DestroyOffsetStruct(psOffsetStruct);
}
LinuxUnLockMutex(&g_sMMapMutex);
-
+
+ if(psFlushMemArea)
+ {
+ OSInvalidateCPUCacheRangeKM(psFlushMemArea, ui32ByteOffset, pvBase,
+ psFlushMemArea->ui32ByteSize);
+ }
+
return iRetVal;
}
@@ -1372,6 +1341,11 @@ PVRMMapExt(struct file* pFile, struct vm_area_struct* ps_vma)
IMG_UINT32 ui32ByteSize;
PKV_OFFSET_STRUCT psOffsetStruct;
+ /* for cache maintenance: */
+ LinuxMemArea *psFlushMemArea = IMG_NULL;
+ IMG_VOID *pvBase = IMG_NULL;
+ IMG_UINT32 ui32ByteOffset = 0; /* Keep compiler happy */
+
PVR_UNREFERENCED_PARAMETER(pFile);
LinuxLockMutex(&g_sMMapMutex);
@@ -1390,16 +1364,44 @@ PVRMMapExt(struct file* pFile, struct vm_area_struct* ps_vma)
list_del(&psOffsetStruct->sMMapItem);
psOffsetStruct->bOnMMapList = IMG_FALSE;
+ if(!DoMapToUser(psOffsetStruct->psLinuxMemArea, ps_vma, 0))
+ {
+ goto unlock_and_return;
+ }
+
PVR_ASSERT(psOffsetStruct->ui32UserVAddr == 0);
psOffsetStruct->ui32UserVAddr = ps_vma->vm_start;
obj->driver_private = psOffsetStruct->psLinuxMemArea;
+
+ /* Compute the flush region (if necessary) inside the mmap mutex */
+ if(psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate)
+ {
+ IMG_UINT32 ui32DummyByteSize;
+
+ DetermineUsersSizeAndByteOffset(psOffsetStruct->psLinuxMemArea,
+ &ui32DummyByteSize,
+ &ui32ByteOffset);
+
+ pvBase = (IMG_VOID *)ps_vma->vm_start + ui32ByteOffset;
+ psFlushMemArea = psOffsetStruct->psLinuxMemArea;
+
+ psOffsetStruct->psLinuxMemArea->bNeedsCacheInvalidate = IMG_FALSE;
+ }
+
+ /* Call the open routine to increment the usage count */
MMapVOpenNoLock(ps_vma, psOffsetStruct);
unlock_and_return:
LinuxUnLockMutex(&g_sMMapMutex);
+
+ if(psFlushMemArea)
+ {
+ OSInvalidateCPUCacheRangeKM(psFlushMemArea, ui32ByteOffset, pvBase,
+ psFlushMemArea->ui32ByteSize);
+ }
}
static struct omap_gem_vm_ops gem_ops = {
@@ -1411,6 +1413,13 @@ static struct omap_gem_vm_ops gem_ops = {
#if defined(DEBUG_LINUX_MMAP_AREAS)
+/*
+ * Lock MMap regions list (called on page start/stop while reading /proc/mmap)
+
+ * sfile : seq_file that handles /proc file
+ * start : TRUE if it's start, FALSE if it's stop
+ *
+*/
static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL start)
{
if(start)
@@ -1424,6 +1433,16 @@ static void ProcSeqStartstopMMapRegistations(struct seq_file *sfile,IMG_BOOL sta
}
+/*
+ * Convert offset (index from KVOffsetTable) to element
+ * (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element that will be dumped
+ *
+*/
static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t off)
{
LinuxMemArea *psLinuxMemArea;
@@ -1449,12 +1468,28 @@ static void* ProcSeqOff2ElementMMapRegistrations(struct seq_file *sfile, loff_t
return (void*)0;
}
+/*
+ * Gets next MMap element to show. (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element to show (0 ends iteration)
+*/
static void* ProcSeqNextMMapRegistrations(struct seq_file *sfile,void* el,loff_t off)
{
return ProcSeqOff2ElementMMapRegistrations(sfile,off);
}
+/*
+ * Show MMap element (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ *
+*/
static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
{
KV_OFFSET_STRUCT *psOffsetStruct = (KV_OFFSET_STRUCT*)el;
@@ -1528,6 +1563,20 @@ static void ProcSeqShowMMapRegistrations(struct seq_file *sfile, void *el)
#endif
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapRegisterArea
+
+ @Description
+
+ Register a memory area with the mmap code.
+
+ @input psLinuxMemArea : pointer to memory area.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
{
@@ -1546,7 +1595,7 @@ PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC || LinuxMemAreaRoot(psLinuxMemArea)->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
-
+ /* Check this mem area hasn't already been registered */
if(psLinuxMemArea->bMMapRegistered)
{
PVR_DPF((PVR_DBG_ERROR, "%s: psLinuxMemArea 0x%p is already registered",
@@ -1561,7 +1610,11 @@ PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea)
#if defined(DEBUG_LINUX_MMAP_AREAS)
g_ui32RegisteredAreas++;
-
+ /*
+ * Sub memory areas are excluded from g_ui32TotalByteSize so that we
+ * don't count memory twice, once for the parent and again for sub
+ * allocationis.
+ */
if (psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC)
{
g_ui32TotalByteSize += psLinuxMemArea->ui32ByteSize;
@@ -1577,6 +1630,20 @@ exit_unlock:
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapRemoveRegisterArea
+
+ @Description
+
+ Unregister a memory area with the mmap code.
+
+ @input psLinuxMemArea : pointer to memory area.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
{
@@ -1592,12 +1659,19 @@ PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea)
if (psOffsetStruct->ui32Mapped != 0)
{
PVR_DPF((PVR_DBG_ERROR, "%s: psOffsetStruct 0x%p for memory area 0x0x%p is still mapped; psOffsetStruct->ui32Mapped %u", __FUNCTION__, psOffsetStruct, psLinuxMemArea, psOffsetStruct->ui32Mapped));
+ dump_stack();
+ PVRSRVDumpRefCountCCB();
eError = PVRSRV_ERROR_STILL_MAPPED;
goto exit_unlock;
}
else
{
-
+ /*
+ * An offset structure is created when a call is made to get
+ * the mmap data for a physical mapping. If the data is never
+ * used for mmap, we will be left with an umapped offset
+ * structure.
+ */
PVR_DPF((PVR_DBG_WARNING, "%s: psOffsetStruct 0x%p was never mapped", __FUNCTION__, psOffsetStruct));
}
@@ -1626,6 +1700,20 @@ exit_unlock:
}
+/*!
+ *******************************************************************************
+
+ @Function LinuxMMapPerProcessConnect
+
+ @Description
+
+ Per-process mmap initialisation code.
+
+ @input psEnvPerProc : pointer to OS specific per-process data.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR
LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
{
@@ -1634,6 +1722,18 @@ LinuxMMapPerProcessConnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
return PVRSRV_OK;
}
+/*!
+ *******************************************************************************
+
+ @Function LinuxMMapPerProcessDisconnect
+
+ @Description
+
+ Per-process mmap deinitialisation code.
+
+ @input psEnvPerProc : pointer to OS specific per-process data.
+
+ ******************************************************************************/
IMG_VOID
LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
{
@@ -1665,6 +1765,20 @@ LinuxMMapPerProcessDisconnect(PVRSRV_ENV_PER_PROCESS_DATA *psEnvPerProc)
}
+/*!
+ *******************************************************************************
+
+ @Function LinuxMMapPerProcessHandleOptions
+
+ @Description
+
+ Set secure handle options required by mmap code.
+
+ @input psHandleBase : pointer to handle base.
+
+ @Return PVRSRV_OK, or PVRSRV_ERROR.
+
+ ******************************************************************************/
PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
{
PVRSRV_ERROR eError;
@@ -1680,6 +1794,16 @@ PVRSRV_ERROR LinuxMMapPerProcessHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase)
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapInit
+
+ @Description
+
+ MMap initialisation code
+
+ ******************************************************************************/
IMG_VOID
PVRMMapInit(IMG_VOID)
{
@@ -1699,7 +1823,7 @@ PVRMMapInit(IMG_VOID)
ProcSeqOff2ElementMMapRegistrations,
ProcSeqStartstopMMapRegistations
);
-#endif
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
return;
error:
@@ -1708,6 +1832,16 @@ error:
}
+/*!
+ *******************************************************************************
+
+ @Function PVRMMapCleanup
+
+ @Description
+
+ Mmap deinitialisation code
+
+ ******************************************************************************/
IMG_VOID
PVRMMapCleanup(IMG_VOID)
{
@@ -1736,7 +1870,7 @@ PVRMMapCleanup(IMG_VOID)
#if defined(DEBUG_LINUX_MMAP_AREAS)
RemoveProcEntrySeq(g_ProcMMap);
-#endif
+#endif /* defined(DEBUG_LINUX_MMAP_AREAS) */
if(g_psMemmapCache)
{
diff --git a/sgx/services4/srvkm/env/linux/mmap.h b/sgx/services4/srvkm/env/linux/mmap.h
index 07d521b..bca8358 100644
--- a/sgx/services4/srvkm/env/linux/mmap.h
+++ b/sgx/services4/srvkm/env/linux/mmap.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mmap interface declaration
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if !defined(__MMAP_H__)
#define __MMAP_H__
@@ -31,68 +47,146 @@
#include <linux/list.h>
#if defined(VM_MIXEDMAP)
+/*
+ * Mixed maps allow us to avoid using raw PFN mappings (VM_PFNMAP) for
+ * pages without pages structures ("struct page"), giving us more
+ * freedom in choosing the mmap offset for mappings. Mixed maps also
+ * allow both the mmap and the wrap code to be simplified somewhat.
+ */
#define PVR_MAKE_ALL_PFNS_SPECIAL
#endif
#include "perproc.h"
#include "mm.h"
+/*
+ * This structure represents the relationship between an mmap2 file
+ * offset and a LinuxMemArea for a given process.
+ */
typedef struct KV_OFFSET_STRUCT_TAG
{
-
+ /*
+ * Mapping count. Incremented when the mapping is created, and
+ * if the mapping is inherited across a process fork.
+ */
IMG_UINT32 ui32Mapped;
-
+ /*
+ * Offset to be passed to mmap2 to map the associated memory area
+ * into user space. The offset may represent the page frame number
+ * of the first page in the area (if the area is physically
+ * contiguous), or it may represent the secure handle associated
+ * with the area.
+ */
IMG_UINT32 ui32MMapOffset;
IMG_UINT32 ui32RealByteSize;
-
+ /* Memory area associated with this offset structure */
LinuxMemArea *psLinuxMemArea;
#if !defined(PVR_MAKE_ALL_PFNS_SPECIAL)
-
+ /* ID of the thread that owns this structure */
IMG_UINT32 ui32TID;
#endif
-
+ /* ID of the process that owns this structure */
IMG_UINT32 ui32PID;
-
+ /*
+ * For offsets that represent actual page frame numbers, this structure
+ * is temporarily put on a list so that it can be found from the
+ * driver mmap entry point. This flag indicates the structure is
+ * on the list.
+ */
IMG_BOOL bOnMMapList;
-
+ /* Reference count for this structure */
IMG_UINT32 ui32RefCount;
-
+ /*
+ * User mode address of start of mapping. This is not necessarily the
+ * first user mode address of the memory area.
+ */
IMG_UINT32 ui32UserVAddr;
-
+ /* Extra entries to support proc filesystem debug info */
#if defined(DEBUG_LINUX_MMAP_AREAS)
const IMG_CHAR *pszName;
#endif
-
+ /* List entry field for MMap list */
struct list_head sMMapItem;
-
+ /* List entry field for per-memory area list */
struct list_head sAreaItem;
}KV_OFFSET_STRUCT, *PKV_OFFSET_STRUCT;
+/*!
+ *******************************************************************************
+ * @Function Mmap initialisation code
+ ******************************************************************************/
IMG_VOID PVRMMapInit(IMG_VOID);
+/*!
+ *******************************************************************************
+ * @Function Mmap de-initialisation code
+ ******************************************************************************/
IMG_VOID PVRMMapCleanup(IMG_VOID);
+/*!
+ *******************************************************************************
+ * @Function Registers a memory area with the mmap code
+ *
+ * @Input psLinuxMemArea
+ *
+ * @Return PVRSRV_ERROR status
+ ******************************************************************************/
PVRSRV_ERROR PVRMMapRegisterArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ *******************************************************************************
+ * @Function Unregisters a memory area from the mmap code
+ *
+ * @Input psLinuxMemArea
+ *
+ * @Return PVRSRV_ERROR status
+ ******************************************************************************/
PVRSRV_ERROR PVRMMapRemoveRegisteredArea(LinuxMemArea *psLinuxMemArea);
+/*!
+ ******************************************************************************
+ * @Function When a userspace services client, requests to map a memory
+ * area to userspace, this function validates the request and
+ * returns the details that the client must use when calling mmap(2).
+ *
+ * @Input psPerProc Per process data.
+ * @Input hMHandle Handle associated with the memory to map.
+ * This is a (secure) handle to the OS specific
+ * memory handle structure (hOSMemHandle), or
+ * a handle to a structure that contains the
+ * memory handle.
+ * @Output pui32MMapOffset The page aligned offset that the client must
+ * pass to the mmap2 system call.
+ * @Output pui32ByteOffset The real mapping that will be created for the
+ * services client may have a different
+ * size/alignment from it request. This offset
+ * is returned to the client and should be added
+ * to virtual address returned from mmap2 to get
+ * the first address corresponding to its request.
+ * @Output pui32RealByteOffset The size that the mapping will really be,
+ * that the client must also pass to mmap/munmap.
+ *
+ * @Output pui32UserVAddr Pointer to returned user mode address of
+ * mapping.
+ * @Return PVRSRV_ERROR
+ ******************************************************************************/
PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hMHandle,
@@ -104,6 +198,21 @@ PVRSRV_ERROR PVRMMapOSMemHandleToMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 *pui32RealByteSize,
IMG_UINT32 *pui32UserVAddr);
+/*!
+ *******************************************************************************
+
+ @Function Release mmap data.
+
+ @Input psPerProc Per-process data.
+ @Input hMHandle Memory handle.
+
+ @Output pbMUnmap Flag that indicates whether an munmap is
+ required.
+ @Output pui32RealByteSize Location for size of mapping.
+ @Output pui32UserVAddr User mode address to munmap.
+
+ @Return PVRSRV_ERROR
+ ******************************************************************************/
PVRSRV_ERROR
PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
#if defined (SUPPORT_SID_INTERFACE)
@@ -115,12 +224,18 @@ PVRMMapReleaseMMapData(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_UINT32 *pui32RealByteSize,
IMG_UINT32 *pui32UserVAddr);
+/*!
+ *******************************************************************************
+ * @Function driver mmap entry point
+ *
+ * @Input pFile : user file structure
+ *
+ * @Input ps_vma : vm area structure
+ *
+ * @Return 0 for success, -errno for failure.
+ ******************************************************************************/
int PVRMMap(struct file* pFile, struct vm_area_struct* ps_vma);
-IMG_VOID PVRMMapPrepareCpuToGpu(IMG_HANDLE hSmartCache);
-IMG_VOID PVRMMapPrepareGpuToCpu(IMG_HANDLE hSmartCache);
-IMG_HANDLE PVRMMapAllocateSmart(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo);
-IMG_VOID PVRMMapFreeSmart(IMG_HANDLE hSmartCache);
-#endif
+#endif /* __MMAP_H__ */
diff --git a/sgx/services4/srvkm/env/linux/module.c b/sgx/services4/srvkm/env/linux/module.c
index cda7c21..fe31e41 100644
--- a/sgx/services4/srvkm/env/linux/module.c
+++ b/sgx/services4/srvkm/env/linux/module.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux module setup
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -35,13 +51,24 @@
#if defined(SUPPORT_DRI_DRM) && !defined(SUPPORT_DRI_DRM_EXTERNAL)
#define PVR_MOD_STATIC
#else
+ /*
+ * For LDM drivers, define PVR_LDM_MODULE to indicate generic LDM
+ * support is required, besides indicating the exact support
+ * required (e.g. platform, or PCI device).
+ */
#if defined(LDM_PLATFORM)
#define PVR_LDM_PLATFORM_MODULE
+ #define PVR_LDM_DEVICE_CLASS
#define PVR_LDM_MODULE
#else
#if defined(LDM_PCI)
+ #define PVR_LDM_DEVICE_CLASS
#define PVR_LDM_PCI_MODULE
#define PVR_LDM_MODULE
+ #else
+ #if defined(SYS_SHARES_WITH_3PKM)
+ #define PVR_LDM_DEVICE_CLASS
+ #endif
#endif
#endif
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
@@ -72,11 +99,15 @@
#if defined(PVR_LDM_PLATFORM_MODULE)
#include <linux/platform_device.h>
-#endif
+#endif /* PVR_LDM_PLATFORM_MODULE */
#if defined(PVR_LDM_PCI_MODULE)
#include <linux/pci.h>
-#endif
+#endif /* PVR_LDM_PCI_MODULE */
+
+#if defined(PVR_LDM_DEVICE_CLASS)
+#include <linux/device.h>
+#endif /* PVR_LDM_DEVICE_CLASS */
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
#include <asm/uaccess.h>
@@ -102,38 +133,69 @@
#include "private_data.h"
#include "lock.h"
#include "linkage.h"
+#include "buffer_manager.h"
#if defined(SUPPORT_DRI_DRM)
#include "pvr_drm.h"
#endif
+/*
+ * DRVNAME is the name we use to register our driver.
+ * DEVNAME is the name we use to register actual device nodes.
+ */
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
#define DRVNAME PVRSRV_MODNAME
#define DEVNAME PVRSRV_MODNAME
#else
-#define DRVNAME PVRSRV_MODNAME
+#if defined(PVR_LDM_MODULE)
+#define DRVNAME PVR_LDM_DRIVER_REGISTRATION_NAME
+#endif
#define DEVNAME PVRSRV_MODNAME
MODULE_SUPPORTED_DEVICE(DEVNAME);
#endif
+/*
+ * This is all module configuration stuff required by the linux kernel.
+ */
#if defined(PVRSRV_NEED_PVR_DPF)
#include <linux/moduleparam.h>
extern IMG_UINT32 gPVRDebugLevel;
module_param(gPVRDebugLevel, uint, 0644);
MODULE_PARM_DESC(gPVRDebugLevel, "Sets the level of debug output (default 0x7)");
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_DPF) */
-
+#if defined(CONFIG_ION_OMAP)
+#include <linux/ion.h>
+#include <linux/omap_ion.h>
+extern struct ion_device *omap_ion_device;
+struct ion_client *gpsIONClient;
+EXPORT_SYMBOL(gpsIONClient);
+#endif /* defined(CONFIG_ION_OMAP) */
+
+/* PRQA S 3207 2 */ /* ignore 'not used' warning */
EXPORT_SYMBOL(PVRGetDisplayClassJTable);
EXPORT_SYMBOL(PVRGetBufferClassJTable);
#if defined(PVR_LDM_MODULE)
+/*
+ * Device class used for /sys entries (and udev device node creation)
+ */
static struct class *psPvrClass;
#endif
#if defined(SUPPORT_DRI_DRM_EXTERNAL) || !defined(SUPPORT_DRI_DRM)
+/*
+ * This is the major number we use for all nodes in /dev.
+ */
static int AssignedMajorNumber;
#endif
+/*
+ * These are the operations that will be associated with the device node
+ * we create.
+ *
+ * With gcc -W, specifying only the non-null members produces "missing
+ * initializer" warnings.
+*/
#if !defined(SUPPORT_DRI_DRM)
static int PVRSRVOpen(struct inode* pInode, struct file* pFile);
static int PVRSRVRelease(struct inode* pInode, struct file* pFile);
@@ -150,6 +212,7 @@ static struct file_operations pvrsrv_fops =
PVRSRV_LINUX_MUTEX gPVRSRVLock;
+/* PID of process being released */
IMG_UINT32 gui32ReleasePID;
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
@@ -161,12 +224,15 @@ static IMG_UINT32 gPVRPowerLevel;
#if defined(PVR_LDM_PLATFORM_MODULE)
#define LDM_DEV struct platform_device
#define LDM_DRV struct platform_driver
-#endif
+#endif /*PVR_LDM_PLATFORM_MODULE */
#if defined(PVR_LDM_PCI_MODULE)
#define LDM_DEV struct pci_dev
#define LDM_DRV struct pci_driver
-#endif
+#endif /* PVR_LDM_PCI_MODULE */
+/*
+ * This is the driver interface we support.
+ */
#if defined(PVR_LDM_PLATFORM_MODULE) && !defined(SUPPORT_DRI_DRM_EXTERNAL)
static int PVRSRVDriverRemove(LDM_DEV *device);
static int PVRSRVDriverProbe(LDM_DEV *device);
@@ -177,6 +243,7 @@ static int PVRSRVDriverProbe(LDM_DEV *device, const struct pci_device_id *id);
#endif
#if defined(PVR_LDM_PCI_MODULE)
+/* This structure is used by the Linux module code */
struct pci_device_id powervr_id_table[] __devinitdata = {
{PCI_DEVICE(SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID)},
#if defined (SYS_SGX_DEV1_DEVICE_ID)
@@ -238,6 +305,22 @@ static struct platform_device powervr_device = {
};
#endif
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverProbe
+
+ @Description
+
+ See whether a given device is really one we can drive. The platform bus
+ handler has already established that we should be able to service this device
+ because of the name match. We probably don't need to do anything else.
+
+ @input pDevice - the device for which a probe is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(PVR_LDM_PLATFORM_MODULE)
PVR_MOD_STATIC int PVRSRVDriverProbe(LDM_DEV *pDevice)
#endif
@@ -249,14 +332,19 @@ static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device
PVR_TRACE(("PVRSRVDriverProbe(pDevice=%p) (%s)", pDevice, pDevice->name));
-#if 0
-
+#if 0 /* INTEGRATION_POINT */
+ /* Some systems require device-specific system initialisation.
+ * E.g. this lets the OS track a device's dependencies on various
+ * system hardware.
+ *
+ * Note: some systems use this to enable HW that SysAcquireData
+ * will depend on, therefore it must be called first.
+ */
if (PerDeviceSysInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
{
return -EINVAL;
}
#endif
-
#if defined(PVR_LDM_PLATFORM_MODULE)
if (!pDevice->dev.platform_data)
{
@@ -264,21 +352,53 @@ static int __devinit PVRSRVDriverProbe(LDM_DEV *pDevice, const struct pci_device
}
#endif
+ /* SysInitialise only designed to be called once.
+ */
psSysData = SysAcquireDataNoCheck();
- if ( psSysData == IMG_NULL)
+ if (psSysData == IMG_NULL)
{
gpsPVRLDMDev = pDevice;
-
if (SysInitialise() != PVRSRV_OK)
{
return -ENODEV;
}
}
+#if defined(CONFIG_ION_OMAP)
+ gpsIONClient = ion_client_create(omap_ion_device,
+ 1 << ION_HEAP_TYPE_CARVEOUT |
+ 1 << OMAP_ION_HEAP_TYPE_TILER,
+ "pvr");
+ if (IS_ERR_OR_NULL(gpsIONClient))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "PVRSRVDriverProbe: Couldn't create ion client"));
+ return PTR_ERR(gpsIONClient);
+ }
+#endif /* defined(CONFIG_ION_OMAP) */
+
return 0;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverRemove
+
+ @Description
+
+ This call is the opposite of the probe call: it is called when the device is
+ being removed from the driver's control. See the file $KERNELDIR/drivers/
+ base/bus.c:device_release_driver() for the call to this function.
+
+ This is the correct place to clean up anything our driver did while it was
+ asoociated with the device.
+
+ @input pDevice - the device for which driver detachment is happening
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined (PVR_LDM_PLATFORM_MODULE)
PVR_MOD_STATIC int PVRSRVDriverRemove(LDM_DEV *pDevice)
#endif
@@ -290,6 +410,11 @@ static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
PVR_TRACE(("PVRSRVDriverRemove(pDevice=%p)", pDevice));
+#if defined(CONFIG_ION_OMAP)
+ ion_client_destroy(gpsIONClient);
+ gpsIONClient = IMG_NULL;
+#endif
+
SysAcquireData(&psSysData);
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
@@ -305,7 +430,8 @@ static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
gpsPVRLDMDev = IMG_NULL;
-#if 0
+#if 0 /* INTEGRATION_POINT */
+ /* See previous integration point for details. */
if (PerDeviceSysDeInitialise((IMG_PVOID)pDevice) != PVRSRV_OK)
{
return -EINVAL;
@@ -319,59 +445,216 @@ static void __devexit PVRSRVDriverRemove(LDM_DEV *pDevice)
return;
#endif
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) */
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+static PVRSRV_LINUX_MUTEX gsPMMutex;
+static IMG_BOOL bDriverIsSuspended;
+static IMG_BOOL bDriverIsShutdown;
+#endif
#if defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV)
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverShutdown
+
+ @Description
+
+ Suspend device operation for system shutdown. This is called as part of the
+ system halt/reboot process. The driver is put into a quiescent state by
+ setting the power state to D3.
+
+ @input pDevice - the device for which shutdown is requested
+
+ @Return nothing
+
+*****************************************************************************/
PVR_MOD_STATIC void PVRSRVDriverShutdown(LDM_DEV *pDevice)
{
PVR_TRACE(("PVRSRVDriverShutdown(pDevice=%p)", pDevice));
- (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+ LinuxLockMutex(&gsPMMutex);
+
+ if (!bDriverIsShutdown && !bDriverIsSuspended)
+ {
+ /*
+ * Take the bridge mutex, and never release it, to stop
+ * processes trying to use the driver after it has been
+ * shutdown.
+ */
+ LinuxLockMutex(&gPVRSRVLock);
+
+ (void) PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3);
+ }
+
+ bDriverIsShutdown = IMG_TRUE;
+
+ /* The bridge mutex is held on exit */
+ LinuxUnLockMutex(&gsPMMutex);
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) || defined(PVR_DRI_DRM_PLATFORM_DEV) */
#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverSuspend
+
+ @Description
+
+ For 2.6 kernels:
+ Suspend device operation. We always get three calls to this regardless of
+ the state (D1-D3) chosen. The order is SUSPEND_DISABLE, SUSPEND_SAVE_STATE
+ then SUSPEND_POWER_DOWN. We take action as soon as we get the disable call,
+ the other states not being handled by us yet.
+
+ For MontaVista 2.4 kernels:
+ This call gets made once only when someone does something like
+
+ # echo -e -n "suspend powerdown 0" >/sys.devices/legacy/pvrsrv0/power
+
+ The 3rd, numeric parameter (0) in the above has no relevence and is not
+ passed into us. The state parameter is always zero and the level parameter
+ is always SUSPEND_POWER_DOWN. Vive la difference!
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverSuspend(struct pci_dev *pDevice, pm_message_t state)
+#else
int PVRSRVDriverSuspend(struct drm_device *pDevice, pm_message_t state)
+#endif
#else
PVR_MOD_STATIC int PVRSRVDriverSuspend(LDM_DEV *pDevice, pm_message_t state)
#endif
{
+ int res = 0;
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(( "PVRSRVDriverSuspend(pDevice=%p)", pDevice));
- if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) != PVRSRV_OK)
+ LinuxLockMutex(&gsPMMutex);
+
+ if (!bDriverIsSuspended && !bDriverIsShutdown)
{
- return -EINVAL;
+ LinuxLockMutex(&gPVRSRVLock);
+
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D3) == PVRSRV_OK)
+ {
+ /* The bridge mutex will be held until we resume */
+ bDriverIsSuspended = IMG_TRUE;
+ }
+ else
+ {
+ LinuxUnLockMutex(&gPVRSRVLock);
+ res = -EINVAL;
+ }
}
+
+ LinuxUnLockMutex(&gsPMMutex);
#endif
- return 0;
+ return res;
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVDriverResume
+
+ @Description
+
+ Resume device operation following a lull due to earlier suspension. It is
+ implicit we're returning to D0 (fully operational) state. We always get three
+ calls to this using level thus: RESUME_POWER_ON, RESUME_RESTORE_STATE then
+ RESUME_ENABLE. On 2.6 kernels We don't do anything until we get the enable
+ call; on the MontaVista set-up we only ever get the RESUME_POWER_ON call.
+
+ @input pDevice - the device for which resume is requested
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM) && !defined(PVR_DRI_DRM_PLATFORM_DEV)
+#if defined(SUPPORT_DRM_MODESET)
+int PVRSRVDriverResume(struct pci_dev *pDevice)
+#else
int PVRSRVDriverResume(struct drm_device *pDevice)
+#endif
#else
PVR_MOD_STATIC int PVRSRVDriverResume(LDM_DEV *pDevice)
#endif
{
+ int res = 0;
#if !(defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM))
PVR_TRACE(("PVRSRVDriverResume(pDevice=%p)", pDevice));
- if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) != PVRSRV_OK)
+ LinuxLockMutex(&gsPMMutex);
+
+ if (bDriverIsSuspended && !bDriverIsShutdown)
{
- return -EINVAL;
+ if (PVRSRVSetPowerStateKM(PVRSRV_SYS_POWER_STATE_D0) == PVRSRV_OK)
+ {
+ bDriverIsSuspended = IMG_FALSE;
+ LinuxUnLockMutex(&gPVRSRVLock);
+ }
+ else
+ {
+ /* The bridge mutex is not released on failure */
+ res = -EINVAL;
+ }
}
+
+ LinuxUnLockMutex(&gsPMMutex);
#endif
- return 0;
+ return res;
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM) */
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL) && !defined(SUPPORT_DRI_DRM)
+/*
+ * If PVR_LDM_PCI_MODULE is defined (and PVR_MANUAL_POWER_CONTROL is *NOT* defined),
+ * the device can be suspended and resumed without suspending/resuming the
+ * system, by writing values into the power/state sysfs file for the device.
+ * To suspend:
+ * echo -n 2 > power/state
+ * To Resume:
+ * echo -n 0 > power/state
+ *
+ * The problem with this approach is that the device is usually left
+ * powered up; it is the responsibility of the bus driver to remove
+ * the power.
+ *
+ * Defining PVR_MANUAL_POWER_CONTROL is intended to make it easier to
+ * debug power management issues, especially when power is really removed
+ * from the device. It is easier to debug the driver if it is not being
+ * suspended/resumed with the rest of the system.
+ *
+ * When PVR_MANUAL_POWER_CONTROL is defined, the following proc entry is
+ * created:
+ * /proc/pvr/power_control
+ * The driver suspend/resume entry points defined below no longer suspend or
+ * resume the device. To suspend the device, type the following:
+ * echo 2 > /proc/pvr/power_control
+ * To resume the device, type:
+ * echo 0 > /proc/pvr/power_control
+ *
+ * The following example shows how to suspend/resume the device independently
+ * of the rest of the system.
+ * Suspend the device:
+ * echo 2 > /proc/pvr/power_control
+ * Suspend the system. Then you should be able to suspend and resume
+ * as normal. To resume the device type the following:
+ * echo 0 > /proc/pvr/power_control
+ */
+
IMG_INT PVRProcSetPowerLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
{
IMG_CHAR data_buffer[2];
@@ -418,6 +701,23 @@ void ProcSeqShowPowerLevel(struct seq_file *sfile,void* el)
#endif
+/*!
+******************************************************************************
+
+ @Function PVRSRVOpen
+
+ @Description
+
+ Release access the PVR services node - called when a file is closed, whether
+ at exit or using close(2) system call.
+
+ @input pInode - the inode for the file being openeded
+
+ @input pFile - the file handle data for the actual file being opened
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
int PVRSRVOpen(struct drm_device unref__ *dev, struct drm_file *pFile)
#else
@@ -478,6 +778,23 @@ err_unlock:
}
+/*!
+******************************************************************************
+
+ @Function PVRSRVRelease
+
+ @Description
+
+ Release access the PVR services node - called when a file is closed, whether
+ at exit or using close(2) system call.
+
+ @input pInode - the inode for the file being released
+
+ @input pFile - the file handle data for the actual file being released
+
+ @Return 0 for success or <0 for an error.
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
void PVRSRVRelease(void *pvPrivData)
#else
@@ -485,6 +802,7 @@ static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
#endif
{
PVRSRV_FILE_PRIVATE_DATA *psPrivateData;
+ int err = 0;
LinuxLockMutex(&gPVRSRVLock);
@@ -499,7 +817,40 @@ static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
list_del(&psPrivateData->sDRMAuthListItem);
#endif
-
+ if(psPrivateData->hKernelMemInfo)
+ {
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
+
+ /* Look up the meminfo we just exported */
+ if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ psPrivateData->hKernelMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+ err = -EFAULT;
+ goto err_unlock;
+ }
+
+ /* Tell the XProc about the export if required */
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ BM_XProcIndexRelease(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ }
+
+ /* This drops the psMemInfo refcount bumped on export */
+ if(FreeMemCallBackCommon(psKernelMemInfo, 0,
+ PVRSRV_FREE_CALLBACK_ORIGIN_EXTERNAL) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: FreeMemCallBackCommon failed", __FUNCTION__));
+ err = -EFAULT;
+ goto err_unlock;
+ }
+ }
+
+ /* Usually this is the same as OSGetCurrentProcessIDKM(),
+ * but not necessarily (e.g. fork(), child closes last..)
+ */
gui32ReleasePID = psPrivateData->ui32OpenPID;
PVRSRVProcessDisconnect(psPrivateData->ui32OpenPID);
gui32ReleasePID = 0;
@@ -509,18 +860,56 @@ static int PVRSRVRelease(struct inode unref__ * pInode, struct file *pFile)
psPrivateData, psPrivateData->hBlockAlloc);
#if !defined(SUPPORT_DRI_DRM)
- set_private(pFile, IMG_NULL);
+ set_private(pFile, IMG_NULL); /*nulling shared pointer*/
#endif
}
+err_unlock:
LinuxUnLockMutex(&gPVRSRVLock);
-
-#if !defined(SUPPORT_DRI_DRM)
- return 0;
+#if defined(SUPPORT_DRI_DRM)
+ return;
+#else
+ return err;
#endif
}
+/*!
+******************************************************************************
+
+ @Function PVRCore_Init
+
+ @Description
+
+ Insert the driver into the kernel.
+
+ The device major number is allocated by the kernel dynamically. This means
+ that the device node (nominally /dev/pvrsrv) will need to be re-made at boot
+ time if the number changes between subsequent loads of the module. While the
+ number often stays constant between loads this is not guaranteed. The node
+ is made as root on the shell with:
+
+ mknod /dev/pvrsrv c nnn 0
+
+ where nnn is the major number found in /proc/devices for DEVNAME and also
+ reported by the PVR_DPF() - look at the boot log using dmesg' to see this).
+
+ Currently the auto-generated script /etc/init.d/rc.pvr handles creation of
+ the device. In other environments the device may be created either through
+ devfs or sysfs.
+
+ Readable proc-filesystem entries under /proc/pvr are created with
+ CreateProcEntries(). These can be read at runtime to get information about
+ the device (eg. 'cat /proc/pvr/vm')
+
+ __init places the function in a special memory section that the kernel frees
+ once the function has been run. Refer also to module_init() macro call below.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
int PVRCore_Init(void)
#else
@@ -535,11 +924,17 @@ static int __init PVRCore_Init(void)
#endif
#if !defined(SUPPORT_DRI_DRM)
-
+ /*
+ * Must come before attempting to print anything via Services.
+ * For DRM, the initialisation will already have been done.
+ */
PVRDPFInit();
#endif
PVR_TRACE(("PVRCore_Init"));
+#if defined(PVR_LDM_MODULE) || defined(SUPPORT_DRI_DRM)
+ LinuxInitMutex(&gsPMMutex);
+#endif
LinuxInitMutex(&gPVRSRVLock);
if (CreateProcEntries ())
@@ -586,7 +981,7 @@ static int __init PVRCore_Init(void)
goto init_failed;
}
#endif
-#endif
+#endif /* PVR_LDM_PLATFORM_MODULE */
#if defined(PVR_LDM_PCI_MODULE)
if ((error = pci_register_driver(&powervr_driver)) != 0)
@@ -595,10 +990,12 @@ static int __init PVRCore_Init(void)
goto init_failed;
}
-#endif
+#endif /* PVR_LDM_PCI_MODULE */
#else
-
+ /*
+ * Drivers using LDM, will call SysInitialise in the probe/attach code
+ */
if ((eError = SysInitialise()) != PVRSRV_OK)
{
error = -ENODEV;
@@ -611,7 +1008,7 @@ static int __init PVRCore_Init(void)
#endif
goto init_failed;
}
-#endif
+#endif /* !defined(PVR_LDM_MODULE) */
#if !defined(SUPPORT_DRI_DRM)
AssignedMajorNumber = register_chrdev(0, DEVNAME, &pvrsrv_fops);
@@ -625,10 +1022,13 @@ static int __init PVRCore_Init(void)
}
PVR_TRACE(("PVRCore_Init: major device %d", AssignedMajorNumber));
-#endif
+#endif /* !defined(SUPPORT_DRI_DRM) */
#if defined(PVR_LDM_MODULE)
-
+ /*
+ * This code (using GPL symbols) facilitates automatic device
+ * node creation on platforms with udev (or similar).
+ */
psPvrClass = class_create(THIS_MODULE, "pvr");
if (IS_ERR(psPvrClass))
@@ -641,7 +1041,7 @@ static int __init PVRCore_Init(void)
psDev = device_create(psPvrClass, NULL, MKDEV(AssignedMajorNumber, 0),
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26))
NULL,
-#endif
+#endif /* (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,26)) */
DEVNAME);
if (IS_ERR(psDev))
{
@@ -649,7 +1049,7 @@ static int __init PVRCore_Init(void)
error = -EBUSY;
goto destroy_class;
}
-#endif
+#endif /* defined(PVR_LDM_DEVICE_CLASS) */
return 0;
@@ -674,8 +1074,8 @@ sys_deinit:
platform_driver_unregister(&powervr_driver);
#endif
-#else
-
+#else /* defined(PVR_LDM_MODULE) */
+ /* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */
{
SYS_DATA *psSysData;
@@ -685,7 +1085,7 @@ sys_deinit:
(void) SysDeinitialise(psSysData);
}
}
-#endif
+#endif /* defined(PVR_LDM_MODULE) */
init_failed:
PVRMMapCleanup();
LinuxMMCleanup();
@@ -695,9 +1095,34 @@ init_failed:
return error;
-}
+} /*PVRCore_Init*/
+
+
+/*!
+*****************************************************************************
+
+ @Function PVRCore_Cleanup
+
+ @Description
+
+ Remove the driver from the kernel.
+ There's no way we can get out of being unloaded other than panicking; we
+ just do everything and plough on regardless of error.
+ __exit places the function in a special memory section that the kernel frees
+ once the function has been run. Refer also to module_exit() macro call below.
+
+ Note that the for LDM on MontaVista kernels, the positioning of the driver
+ de-registration is the opposite way around than would be suggested by the
+ registration case or the 2,6 kernel case. This is the correct way to do it
+ and the kernel panics if you change it. You have been warned.
+
+ @input none
+
+ @Return none
+
+*****************************************************************************/
#if defined(SUPPORT_DRI_DRM)
void PVRCore_Cleanup(void)
#else
@@ -721,17 +1146,17 @@ static void __exit PVRCore_Cleanup(void)
#if !defined(SUPPORT_DRI_DRM)
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
if (
-#endif
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
unregister_chrdev((IMG_UINT)AssignedMajorNumber, DRVNAME)
#if !(LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22))
;
-#else
+#else /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
)
{
PVR_DPF((PVR_DBG_ERROR," can't unregister device major %d", AssignedMajorNumber));
}
-#endif
-#endif
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,22)) */
+#endif /* !defined(SUPPORT_DRI_DRM) */
#if defined(PVR_LDM_MODULE)
@@ -746,7 +1171,7 @@ static void __exit PVRCore_Cleanup(void)
platform_driver_unregister(&powervr_driver);
#endif
-#else
+#else /* defined(PVR_LDM_MODULE) */
#if defined(DEBUG) && defined(PVR_MANUAL_POWER_CONTROL)
if (gPVRPowerLevel != 0)
{
@@ -756,9 +1181,9 @@ static void __exit PVRCore_Cleanup(void)
}
}
#endif
-
+ /* LDM drivers call SysDeinitialise during PVRSRVDriverRemove */
(void) SysDeinitialise(psSysData);
-#endif
+#endif /* defined(PVR_LDM_MODULE) */
PVRMMapCleanup();
@@ -773,6 +1198,12 @@ static void __exit PVRCore_Cleanup(void)
PVR_TRACE(("PVRCore_Cleanup: unloading"));
}
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver. Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
#if !defined(SUPPORT_DRI_DRM)
module_init(PVRCore_Init);
module_exit(PVRCore_Cleanup);
diff --git a/sgx/services4/srvkm/env/linux/mutex.c b/sgx/services4/srvkm/env/linux/mutex.c
index 742fa03..84e2a74 100644
--- a/sgx/services4/srvkm/env/linux/mutex.c
+++ b/sgx/services4/srvkm/env/linux/mutex.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mutex interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
#include <linux/errno.h>
@@ -79,7 +95,7 @@ IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
}
-#else
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
IMG_VOID LinuxInitMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
@@ -98,7 +114,9 @@ PVRSRV_ERROR LinuxLockMutexInterruptible(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
{
if(down_interruptible(&psPVRSRVMutex->sSemaphore) == -EINTR)
{
-
+ /* The process was sent a signal while waiting for the semaphore
+ * (e.g. a kill signal from userspace)
+ */
return PVRSRV_ERROR_MUTEX_INTERRUPTIBLE_ERROR;
}else{
atomic_dec(&psPVRSRVMutex->Count);
@@ -132,5 +150,5 @@ IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex)
return (IMG_BOOL)iCount;
}
-#endif
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
diff --git a/sgx/services4/srvkm/env/linux/mutex.h b/sgx/services4/srvkm/env/linux/mutex.h
index 5e787b7..2c7d658 100644
--- a/sgx/services4/srvkm/env/linux/mutex.h
+++ b/sgx/services4/srvkm/env/linux/mutex.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux mutex interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
#ifndef __INCLUDED_LINUX_MUTEX_H_
#define __INCLUDED_LINUX_MUTEX_H_
@@ -41,12 +58,16 @@
typedef struct mutex PVRSRV_LINUX_MUTEX;
-#else
+#else /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15)) */
typedef struct {
struct semaphore sSemaphore;
-
+ /* since Linux's struct semaphore is intended to be
+ * opaque we don't poke inside for the count and
+ * instead we track it outselves. (So we can implement
+ * LinuxIsLockedMutex)
+ */
atomic_t Count;
}PVRSRV_LINUX_MUTEX;
@@ -66,5 +87,5 @@ extern IMG_VOID LinuxUnLockMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
extern IMG_BOOL LinuxIsLockedMutex(PVRSRV_LINUX_MUTEX *psPVRSRVMutex);
-#endif
+#endif /* __INCLUDED_LINUX_MUTEX_H_ */
diff --git a/sgx/services4/srvkm/env/linux/mutils.c b/sgx/services4/srvkm/env/linux/mutils.c
index a012cf5..9679ed7 100644
--- a/sgx/services4/srvkm/env/linux/mutils.c
+++ b/sgx/services4/srvkm/env/linux/mutils.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux memory interface support functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -77,15 +93,23 @@ pvr_pat_entry(u64 pat, IMG_UINT index)
static IMG_VOID
PVRLinuxX86PATProbe(IMG_VOID)
{
-
- if (cpu_has_pat)
+ /*
+ * cpu_has_pat indicates whether PAT support is available on the CPU,
+ * but doesn't indicate if it has been enabled.
+ */
+ if (cpu_has_pat) /* PRQA S 3335 */ /* ignore 'no function declared' */
{
u64 pat;
IMG_UINT pat_index;
IMG_UINT pat_entry;
PVR_TRACE(("%s: PAT available", __FUNCTION__));
-
+ /*
+ * There is no Linux API for finding out if write combining
+ * is avaialable through the PAT, so we take the direct
+ * approach, and see if the PAT MSR contains a write combining
+ * entry.
+ */
rdmsrl(MSR_IA32_CR_PAT, pat);
PVR_TRACE(("%s: Top 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat >> 32)));
PVR_TRACE(("%s: Bottom 32 bits of PAT: 0x%.8x", __FUNCTION__, (IMG_UINT)(pat)));
@@ -110,21 +134,28 @@ PVRLinuxX86PATProbe(IMG_VOID)
{
PVR_TRACE(("%s: Write combining not available", __FUNCTION__));
}
-#else
+#else /* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */
PVR_TRACE(("%s: Write combining disabled in driver build", __FUNCTION__));
-#endif
-#endif
+#endif /* defined(SUPPORT_LINUX_X86_WRITECOMBINE) */
+#endif /* DEBUG */
}
pgprot_t
pvr_pgprot_writecombine(pgprot_t prot)
{
-
-
+ /*
+ * It would be worth checking from time to time to see if a
+ * pgprot_writecombine function (or similar) is introduced on Linux for
+ * x86 processors. If so, this function, and PVRLinuxX86PATProbe can be
+ * removed, and a macro used to select between pgprot_writecombine and
+ * pgprot_noncached, dpending on the value for of
+ * SUPPORT_LINUX_X86_WRITECOMBINE.
+ */
+ /* PRQA S 0481,0482 2 */ /* scalar expressions */
return (g_write_combining_available) ?
__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_MASK) | _PAGE_CACHE_WC) : pgprot_noncached(prot);
}
-#endif
+#endif /* defined(SUPPORT_LINUX_X86_PAT) */
IMG_VOID
PVRLinuxMUtilsInit(IMG_VOID)
diff --git a/sgx/services4/srvkm/env/linux/mutils.h b/sgx/services4/srvkm/env/linux/mutils.h
index b2a8ba0..4921e60 100644
--- a/sgx/services4/srvkm/env/linux/mutils.h
+++ b/sgx/services4/srvkm/env/linux/mutils.h
@@ -1,29 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Memory management support utils
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Declares various memory management support functions
+ for Linux.
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __IMG_LINUX_MUTILS_H__
#define __IMG_LINUX_MUTILS_H__
@@ -99,5 +116,5 @@
IMG_VOID PVRLinuxMUtilsInit(IMG_VOID);
-#endif
+#endif /* __IMG_LINUX_MUTILS_H__ */
diff --git a/sgx/services4/srvkm/env/linux/osfunc.c b/sgx/services4/srvkm/env/linux/osfunc.c
index 1fb99f2..4e4b3a0 100644
--- a/sgx/services4/srvkm/env/linux/osfunc.c
+++ b/sgx/services4/srvkm/env/linux/osfunc.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Environment related functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -74,6 +90,15 @@
#include "event.h"
#include "linkage.h"
#include "pvr_uaccess.h"
+#include "lock.h"
+
+#if defined (SUPPORT_ION)
+#include "ion.h"
+#endif
+
+#if defined (CONFIG_X86_PAE)
+#error Physical Address Extension not supported with the driver
+#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27))
#define ON_EACH_CPU(func, info, wait) on_each_cpu(func, info, wait)
@@ -82,6 +107,13 @@
#endif
#if defined(PVR_LINUX_USING_WORKQUEUES) && !defined(CONFIG_PREEMPT)
+/*
+ * Services spins at certain points waiting for events (e.g. swap
+ * chain destrucion). If those events rely on workqueues running,
+ * it needs to be possible to preempt the waiting thread.
+ * Removing the need for CONFIG_PREEMPT will require adding preemption
+ * points at various points in Services.
+ */
#error "A preemptible Linux kernel is required when using workqueues"
#endif
@@ -89,7 +121,7 @@
#define EVENT_OBJECT_TIMEOUT_MS (2000)
#else
#define EVENT_OBJECT_TIMEOUT_MS (100)
-#endif
+#endif /* EMULATOR */
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID *ppvCpuVAddr, IMG_HANDLE *phBlockAlloc)
@@ -102,7 +134,7 @@ PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOI
if (ui32Size > PAGE_SIZE)
{
-
+ /* Try to allocate the memory using vmalloc */
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
*ppvCpuVAddr = _VMallocWrapper(ui32Size, PVRSRV_HAP_CACHED, pszFilename, ui32Line);
#else
@@ -135,7 +167,7 @@ static inline int is_vmalloc_addr(const void *pvCpuVAddr)
return lAddr >= VMALLOC_START && lAddr < VMALLOC_END;
}
-#endif
+#endif /* (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24)) */
#if !defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_UINT32 ui32Size, IMG_PVOID pvCpuVAddr, IMG_HANDLE hBlockAlloc)
@@ -172,6 +204,9 @@ PVRSRV_ERROR
OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_HANDLE hBMHandle,
IMG_VOID **ppvCpuVAddr,
IMG_HANDLE *phOSMemHandle)
{
@@ -180,7 +215,8 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
PVR_UNREFERENCED_PARAMETER(ui32PageSize);
#if 0
-
+ /* For debug: force all OSAllocPages allocations to have a kernel
+ * virtual address */
if(ui32AllocFlags & PVRSRV_HAP_SINGLE_PROCESS)
{
ui32AllocFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
@@ -188,6 +224,22 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
}
#endif
+ if(ui32AllocFlags & PVRSRV_MEM_ION)
+ {
+ /* We'll only see HAP_SINGLE_PROCESS with MEM_ION */
+ BUG_ON((ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK) != PVRSRV_HAP_SINGLE_PROCESS);
+
+ psLinuxMemArea = NewIONLinuxMemArea(ui32Size, ui32AllocFlags,
+ pvPrivData, ui32PrivDataLength);
+ if(!psLinuxMemArea)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ PVRMMapRegisterArea(psLinuxMemArea);
+ goto ExitSkipSwitch;
+ }
+
switch(ui32AllocFlags & PVRSRV_HAP_MAPTYPE_MASK)
{
case PVRSRV_HAP_KERNEL_ONLY:
@@ -201,8 +253,9 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
}
case PVRSRV_HAP_SINGLE_PROCESS:
{
-
-
+ /* Currently PVRSRV_HAP_SINGLE_PROCESS implies that we dont need a
+ * kernel virtual mapping, but will need a user space virtual mapping */
+
psLinuxMemArea = NewAllocPagesLinuxMemArea(ui32Size, ui32AllocFlags);
if(!psLinuxMemArea)
{
@@ -214,10 +267,18 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
case PVRSRV_HAP_MULTI_PROCESS:
{
-
+ /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+ * virtual mapping and potentially multiple user space virtual
+ * mappings: Note: these eat into our limited kernel virtual
+ * address space. */
+
#if defined(VIVT_CACHE) || defined(__sh__)
-
- ui32AllocFlags &= ~(PVRSRV_HAP_CACHED|PVRSRV_HAP_SMART);
+ /* ARM9 caches are tagged with virtual pages, not physical. As we are going to
+ * share this memory in different address spaces, we don't want it to be cached.
+ * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+ * address aliasing in the TLB, as long as the kernel supports cache colouring for
+ * VIPT architectures. */
+ ui32AllocFlags &= ~PVRSRV_HAP_CACHED;
#endif
psLinuxMemArea = NewVMallocLinuxMemArea(ui32Size, ui32AllocFlags);
if(!psLinuxMemArea)
@@ -234,6 +295,16 @@ OSAllocPages_Impl(IMG_UINT32 ui32AllocFlags,
return PVRSRV_ERROR_INVALID_PARAMS;
}
+ /*
+ In case of sparse mapping we need to handle back to the BM as it
+ knows the mapping info
+ */
+ if (ui32AllocFlags & PVRSRV_MEM_SPARSE)
+ {
+ psLinuxMemArea->hBMHandle = hBMHandle;
+ }
+
+ExitSkipSwitch:
*ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
*phOSMemHandle = psLinuxMemArea;
@@ -302,7 +373,7 @@ OSGetSubMemHandle(IMG_HANDLE hOSMemHandle,
}
*phOSMemHandleRet = psLinuxMemArea;
-
+ /* KERNEL_ONLY areas are never mmapable. */
if(ui32Flags & PVRSRV_HAP_KERNEL_ONLY)
{
return PVRSRV_OK;
@@ -344,23 +415,6 @@ OSReleaseSubMemHandle(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32Flags)
return PVRSRV_OK;
}
-IMG_VOID
-OSMemHandleRegisterSmart(IMG_VOID *hOSMemHandle, IMG_HANDLE hSmartCache)
-{
- LinuxMemArea *psLinuxMemArea = hOSMemHandle;
- psLinuxMemArea->hSmartCache = hSmartCache;
-}
-
-IMG_VOID
-OSMemHandleUnegisterSmart(IMG_VOID *hOSMemHandle, IMG_HANDLE hSmartCache)
-{
- LinuxMemArea *psLinuxMemArea = hOSMemHandle;
- if (psLinuxMemArea->hSmartCache == hSmartCache)
- {
- psLinuxMemArea->hSmartCache = NULL;
- }
-}
-
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
IMG_VOID
@@ -388,7 +442,33 @@ OSMemHandleToCpuPAddr(IMG_VOID *hOSMemHandle, IMG_UINT32 ui32ByteOffset)
}
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle)
+{
+ LinuxMemArea *psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
+
+ PVR_ASSERT(psLinuxMemArea);
+ if(psLinuxMemArea->eAreaType == LINUX_MEM_AREA_EXTERNAL_KV)
+ return psLinuxMemArea->uData.sExternalKV.bPhysContig;
+
+ return IMG_FALSE;
+}
+
+
+/*!
+******************************************************************************
+
+ @Function OSMemCopy
+
+ @Description Copies memory around
+
+ @Input pvDst - pointer to dst
+ @Output pvSrc - pointer to src
+ @Input ui32Size - bytes to copy
+
+ @Return none
+
+******************************************************************************/
IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
{
#if defined(USE_UNOPTIMISED_MEMCPY)
@@ -407,6 +487,22 @@ IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_UINT32 ui32Size)
}
+/*!
+******************************************************************************
+
+ @Function OSMemSet
+
+ @Description Function that does the same as the C memset() functions
+
+ @Modified *pvDest : pointer to start of buffer to be set
+
+ @Input ui8Value: value to set each byte to
+
+ @Input ui32Size : number of bytes to set
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
{
#if defined(USE_UNOPTIMISED_MEMSET)
@@ -424,11 +520,21 @@ IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_UINT32 ui32Size)
}
+/*!
+******************************************************************************
+ @Function OSStringCopy
+ @Description strcpy
+******************************************************************************/
IMG_CHAR *OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc)
{
return (strcpy(pszDest, pszSrc));
}
+/*!
+******************************************************************************
+ @Function OSSNPrintf
+ @Description snprintf
+******************************************************************************/
IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFormat, ...)
{
va_list argList;
@@ -441,6 +547,19 @@ IMG_INT32 OSSNPrintf(IMG_CHAR *pStr, IMG_UINT32 ui32Size, const IMG_CHAR *pszFor
return iCount;
}
+/*!
+******************************************************************************
+
+ @Function OSBreakResourceLock
+
+ @Description unlocks an OS dependant resource
+
+ @Input phResource - pointer to OS dependent resource structure
+ @Input ui32ID - Lock value to look for
+
+ @Return
+
+******************************************************************************/
IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
{
volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
@@ -464,6 +583,18 @@ IMG_VOID OSBreakResourceLock (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
}
+/*!
+******************************************************************************
+
+ @Function OSCreateResource
+
+ @Description creates a OS dependant resource object
+
+ @Input phResource - pointer to OS dependent resource
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
{
psResource->ui32ID = 0;
@@ -473,6 +604,18 @@ PVRSRV_ERROR OSCreateResource(PVRSRV_RESOURCE *psResource)
}
+/*!
+******************************************************************************
+
+ @Function OSDestroyResource
+
+ @Description destroys an OS dependant resource object
+
+ @Input phResource - pointer to OS dependent resource
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
{
OSBreakResourceLock (psResource, psResource->ui32ID);
@@ -481,12 +624,26 @@ PVRSRV_ERROR OSDestroyResource (PVRSRV_RESOURCE *psResource)
}
+/*!
+******************************************************************************
+
+ @Function OSInitEnvData
+
+ @Description Allocates space for env specific data
+
+ @Input ppvEnvSpecificData - pointer to pointer in which to return
+ allocated data.
+ @Input ui32MMUMode - MMU mode.
+
+ @Return nothing
+
+******************************************************************************/
PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
{
ENV_DATA *psEnvData;
PVRSRV_ERROR eError;
-
+ /* allocate env specific data */
eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), (IMG_VOID **)&psEnvData, IMG_NULL,
"Environment Data");
if (eError != PVRSRV_OK)
@@ -500,22 +657,34 @@ PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData)
if (eError != PVRSRV_OK)
{
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), psEnvData, IMG_NULL);
-
+ /*not nulling pointer, out of scope*/
return eError;
}
-
+ /* ISR installation flags */
psEnvData->bMISRInstalled = IMG_FALSE;
psEnvData->bLISRInstalled = IMG_FALSE;
-
+ /* copy structure back */
*ppvEnvSpecificData = psEnvData;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSDeInitEnvData
+
+ @Description frees env specific data memory
+
+ @Input pvEnvSpecificData - pointer to private structure
+
+ @Return PVRSRV_OK on success else PVRSRV_ERROR_OUT_OF_MEMORY
+
+******************************************************************************/
PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
{
ENV_DATA *psEnvData = (ENV_DATA*)pvEnvSpecificData;
@@ -527,20 +696,42 @@ PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData)
psEnvData->pvBridgeData = IMG_NULL;
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(ENV_DATA), pvEnvSpecificData, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSReleaseThreadQuanta
+ @Description
+ Releases thread quanta
+
+ @Return nothing
+
+******************************************************************************/
IMG_VOID OSReleaseThreadQuanta(IMG_VOID)
{
schedule();
}
+/*!
+******************************************************************************
+
+ @Function OSClockus
+
+ @Description
+ This function returns the clock in microseconds
+ @Input void
+
+ @Return - clock (us)
+
+******************************************************************************/
IMG_UINT32 OSClockus(IMG_VOID)
{
IMG_UINT32 time, j = jiffies;
@@ -563,25 +754,71 @@ IMG_VOID OSSleepms(IMG_UINT32 ui32Timems)
}
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerCreate
+ @Description
+ This function creates a high res timer who's handle is returned
+
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/
IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID)
{
-
+ /* We don't need a handle, but we must return non-NULL */
return (IMG_HANDLE) 1;
}
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerGetus
+
+ @Description
+ This function returns the current timestamp in us
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/
IMG_UINT32 OSFuncHighResTimerGetus(IMG_HANDLE hTimer)
{
return (IMG_UINT32) jiffies_to_usecs(jiffies);
}
+/*!
+******************************************************************************
+
+ @Function OSFuncHighResTimerDestroy
+ @Description
+ This function will destroy the high res timer
+
+ @Input nothing
+
+ @Return handle
+
+******************************************************************************/
IMG_VOID OSFuncHighResTimerDestroy(IMG_HANDLE hTimer)
{
PVR_UNREFERENCED_PARAMETER(hTimer);
}
+/*!
+******************************************************************************
+
+ @Function OSGetCurrentProcessIDKM
+
+ @Description Returns handle for current process
+
+ @Return ID of current process
+
+*****************************************************************************/
IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
{
if (in_interrupt())
@@ -601,6 +838,16 @@ IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID)
}
+/*!
+******************************************************************************
+
+ @Function OSGetPageSize
+
+ @Description gets page size
+
+ @Return page size
+
+******************************************************************************/
IMG_UINT32 OSGetPageSize(IMG_VOID)
{
#if defined(__sh__)
@@ -613,6 +860,16 @@ IMG_UINT32 OSGetPageSize(IMG_VOID)
}
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0))
+/*!
+******************************************************************************
+
+ @Function DeviceISRWrapper
+
+ @Description wrapper for Device ISR function to conform to ISR OS interface
+
+ @Return
+
+******************************************************************************/
static irqreturn_t DeviceISRWrapper(int irq, void *dev_id
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
, struct pt_regs *regs
@@ -649,6 +906,19 @@ out:
+/*!
+******************************************************************************
+
+ @Function SystemISRWrapper
+
+ @Description wrapper for System ISR function to conform to ISR OS interface
+
+ @Input Interrupt - NT interrupt object.
+ @Input Context - Context parameter
+
+ @Return
+
+******************************************************************************/
static irqreturn_t SystemISRWrapper(int irq, void *dev_id
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19))
, struct pt_regs *regs
@@ -682,6 +952,21 @@ out:
return bStatus ? IRQ_HANDLED : IRQ_NONE;
#endif
}
+/*!
+******************************************************************************
+
+ @Function OSInstallDeviceLISR
+
+ @Description Installs a Device ISR
+
+ @Input pvSysData
+ @Input ui32Irq - IRQ number
+ @Input pszISRName - ISR name
+ @Input pvDeviceNode - device node contains ISR function and data argument
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
IMG_UINT32 ui32Irq,
IMG_CHAR *pszISRName,
@@ -718,6 +1003,18 @@ PVRSRV_ERROR OSInstallDeviceLISR(IMG_VOID *pvSysData,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallDeviceLISR
+
+ @Description Uninstalls a Device ISR
+
+ @Input pvSysData - sysdata
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -739,6 +1036,19 @@ PVRSRV_ERROR OSUninstallDeviceLISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function OSInstallSystemLISR
+
+ @Description Installs a System ISR
+
+ @Input psSysData
+ @Input ui32Irq - IRQ number
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -773,6 +1083,18 @@ PVRSRV_ERROR OSInstallSystemLISR(IMG_VOID *pvSysData, IMG_UINT32 ui32Irq)
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallSystemLISR
+
+ @Description Uninstalls a System ISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -794,6 +1116,18 @@ PVRSRV_ERROR OSUninstallSystemLISR(IMG_VOID *pvSysData)
}
#if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE)
+/*!
+******************************************************************************
+
+ @Function MISRWrapper
+
+ @Description OS dependent MISR wrapper
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
static void MISRWrapper(
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
void *data
@@ -809,6 +1143,18 @@ static void MISRWrapper(
}
+/*!
+******************************************************************************
+
+ @Function OSInstallMISR
+
+ @Description Installs an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -843,6 +1189,18 @@ PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallMISR
+
+ @Description Uninstalls an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -864,6 +1222,18 @@ PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function OSScheduleMISR
+
+ @Description Schedules an OS dependent MISR
+
+ @Input pvSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -876,8 +1246,20 @@ PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
return PVRSRV_OK;
}
-#else
+#else /* defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
#if defined(PVR_LINUX_MISR_USING_WORKQUEUE)
+/*!
+******************************************************************************
+
+ @Function MISRWrapper
+
+ @Description OS dependent MISR wrapper
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
static void MISRWrapper(
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20))
void *data
@@ -893,6 +1275,18 @@ static void MISRWrapper(
}
+/*!
+******************************************************************************
+
+ @Function OSInstallMISR
+
+ @Description Installs an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -919,6 +1313,18 @@ PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallMISR
+
+ @Description Uninstalls an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -940,6 +1346,18 @@ PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function OSScheduleMISR
+
+ @Description Schedules an OS dependent MISR
+
+ @Input pvSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -953,9 +1371,21 @@ PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
return PVRSRV_OK;
}
-#else
+#else /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+/*!
+******************************************************************************
+
+ @Function MISRWrapper
+
+ @Description OS dependent MISR wrapper
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
static void MISRWrapper(unsigned long data)
{
SYS_DATA *psSysData;
@@ -966,6 +1396,18 @@ static void MISRWrapper(unsigned long data)
}
+/*!
+******************************************************************************
+
+ @Function OSInstallMISR
+
+ @Description Installs an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -987,6 +1429,18 @@ PVRSRV_ERROR OSInstallMISR(IMG_VOID *pvSysData)
}
+/*!
+******************************************************************************
+
+ @Function OSUninstallMISR
+
+ @Description Uninstalls an OS dependent MISR
+
+ @Input psSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -1007,6 +1461,18 @@ PVRSRV_ERROR OSUninstallMISR(IMG_VOID *pvSysData)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSScheduleMISR
+
+ @Description Schedules an OS dependent MISR
+
+ @Input pvSysData
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
{
SYS_DATA *psSysData = (SYS_DATA*)pvSysData;
@@ -1020,10 +1486,10 @@ PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData)
return PVRSRV_OK;
}
-#endif
-#endif
+#endif /* #if defined(PVR_LINUX_MISR_USING_WORKQUEUE) */
+#endif /* #if defined(PVR_LINUX_MISR_USING_PRIVATE_WORKQUEUE) */
-#endif
+#endif /* #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)) */
IMG_VOID OSPanic(IMG_VOID)
{
@@ -1035,6 +1501,19 @@ IMG_VOID OSPanic(IMG_VOID)
#else
#define OS_TAS(p) tas(p)
#endif
+/*!
+******************************************************************************
+
+ @Function OSLockResource
+
+ @Description locks an OS dependant Resource
+
+ @Input phResource - pointer to OS dependent Resource
+ @Input bBlock - do we want to block?
+
+ @Return error status
+
+******************************************************************************/
PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
IMG_UINT32 ui32ID)
@@ -1050,6 +1529,18 @@ PVRSRV_ERROR OSLockResource ( PVRSRV_RESOURCE *psResource,
}
+/*!
+******************************************************************************
+
+ @Function OSUnlockResource
+
+ @Description unlocks an OS dependant resource
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return
+
+******************************************************************************/
PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
{
volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
@@ -1080,6 +1571,18 @@ PVRSRV_ERROR OSUnlockResource (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
}
+/*!
+******************************************************************************
+
+ @Function OSIsResourceLocked
+
+ @Description tests if resource is locked
+
+ @Input phResource - pointer to OS dependent resource structure
+
+ @Return error status
+
+******************************************************************************/
IMG_BOOL OSIsResourceLocked (PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID)
{
volatile IMG_UINT32 *pui32Access = (volatile IMG_UINT32 *)&psResource->ui32Lock;
@@ -1101,7 +1604,7 @@ PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock)
IMG_VOID OSPowerLockUnwrap (IMG_VOID)
{
}
-#endif
+#endif /* SYS_CUSTOM_POWERLOCK_WRAP */
IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
@@ -1114,8 +1617,6 @@ IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
PVR_ASSERT(hOSMemHandle != IMG_NULL);
-
-
psLinuxMemArea = (LinuxMemArea *)hOSMemHandle;
uiByteOffset = (IMG_UINTPTR_T)pvLinAddr - (IMG_UINTPTR_T)LinuxMemAreaToCpuVAddr(psLinuxMemArea);
@@ -1127,6 +1628,22 @@ IMG_CPU_PHYADDR OSMapLinToCPUPhys(IMG_HANDLE hOSMemHandle,
}
+/*!
+******************************************************************************
+
+ @Function OSMapPhysToLin
+
+ @Description Maps the physical memory into linear addr range
+
+ @Input BasePAddr : physical cpu address
+
+ @Input ui32Bytes - bytes to map
+
+ @Input ui32CacheType - cache type
+
+ @Return : Linear addr of mapping on success, else NULL
+
+ ******************************************************************************/
IMG_VOID *
OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
IMG_UINT32 ui32Bytes,
@@ -1135,7 +1652,11 @@ OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
{
if(ui32MappingFlags & PVRSRV_HAP_KERNEL_ONLY)
{
-
+ /*
+ * Provide some backwards compatibility, until all callers
+ * have been updated to pass a non-null OSMemHandle pointer.
+ * Such callers must not call OSMapLinToCPUPhys.
+ */
if(phOSMemHandle == IMG_NULL)
{
IMG_VOID *pvIORemapCookie;
@@ -1167,6 +1688,12 @@ OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr,
return IMG_NULL;
}
+/*!
+******************************************************************************
+ @Function OSUnMapPhysToLin
+ @Description Unmaps memory that was mapped with OSMapPhysToLin
+ @Return TRUE on success, else FALSE
+******************************************************************************/
IMG_BOOL
OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32MappingFlags, IMG_HANDLE hOSMemHandle)
{
@@ -1198,6 +1725,12 @@ OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_UINT32 ui32Bytes, IMG_UINT32 ui32Mappi
return IMG_FALSE;
}
+/*!
+******************************************************************************
+ @Function RegisterExternalMem
+ @Description Registers external memory for user mode mapping
+ @Return TRUE on success, else FALSE, MemHandle out
+******************************************************************************/
static PVRSRV_ERROR
RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
IMG_VOID *pvCPUVAddr,
@@ -1233,10 +1766,19 @@ RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
}
case PVRSRV_HAP_MULTI_PROCESS:
{
-
+ /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+ * virtual mapping and potentially multiple user space virtual mappings.
+ * Beware that the kernel virtual address space is a limited resource.
+ */
#if defined(VIVT_CACHE) || defined(__sh__)
-
- ui32MappingFlags &= ~(PVRSRV_HAP_CACHED|PVRSRV_HAP_SMART);
+ /*
+ * ARM9 caches are tagged with virtual pages, not physical. As we are going to
+ * share this memory in different address spaces, we don't want it to be cached.
+ * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+ * address aliasing in the TLB, as long as the kernel supports cache colouring for
+ * VIPT architectures.
+ */
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
#endif
psLinuxMemArea = NewExternalKVLinuxMemArea(pBasePAddr, pvCPUVAddr, ui32Bytes, bPhysContig, ui32MappingFlags);
@@ -1261,6 +1803,13 @@ RegisterExternalMem(IMG_SYS_PHYADDR *pBasePAddr,
}
+/*!
+******************************************************************************
+ @Function OSRegisterMem
+ @Description Registers external memory for user mode mapping
+ @Output phOSMemHandle - handle to registered memory
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
IMG_VOID *pvCPUVAddr,
@@ -1280,6 +1829,12 @@ PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr, IMG_VOID *pvCPU
}
+/*!
+******************************************************************************
+ @Function OSUnRegisterMem
+ @Description UnRegisters external memory for user mode mapping
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSUnRegisterMem (IMG_VOID *pvCpuVAddr,
IMG_UINT32 ui32Bytes,
@@ -1326,17 +1881,27 @@ PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr, IMG_UINT32 ui32Bytes
return OSUnRegisterMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
}
+/*!
+******************************************************************************
+ @Function OSReservePhys
+ @Description Registers physical memory for user mode mapping
+ @Output ppvCpuVAddr
+ @Output phOsMemHandle handle to registered memory
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
IMG_UINT32 ui32Bytes,
IMG_UINT32 ui32MappingFlags,
+ IMG_HANDLE hBMHandle,
IMG_VOID **ppvCpuVAddr,
IMG_HANDLE *phOSMemHandle)
{
LinuxMemArea *psLinuxMemArea;
#if 0
-
+ /* For debug: force all OSReservePhys reservations to have a kernel
+ * virtual address */
if(ui32MappingFlags & PVRSRV_HAP_SINGLE_PROCESS)
{
ui32MappingFlags &= ~PVRSRV_HAP_SINGLE_PROCESS;
@@ -1348,7 +1913,10 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
{
case PVRSRV_HAP_KERNEL_ONLY:
{
-
+ /* Currently PVRSRV_HAP_KERNEL_ONLY implies that a kernel virtual
+ * mapping is required for the allocation and no user virtual
+ * mappings are allowed: Note these eat into our limited kernel
+ * virtual address space */
psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
@@ -1358,7 +1926,8 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
}
case PVRSRV_HAP_SINGLE_PROCESS:
{
-
+ /* Currently this implies that we dont need a kernel virtual
+ * mapping, but will need a user space virtual mapping */
psLinuxMemArea = NewIOLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
if(!psLinuxMemArea)
{
@@ -1369,10 +1938,19 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
}
case PVRSRV_HAP_MULTI_PROCESS:
{
-
+ /* Currently PVRSRV_HAP_MULTI_PROCESS implies that we need a kernel
+ * virtual mapping and potentially multiple user space virtual mappings.
+ * Beware that the kernel virtual address space is a limited resource.
+ */
#if defined(VIVT_CACHE) || defined(__sh__)
-
- ui32MappingFlags &= ~(PVRSRV_HAP_CACHED|PVRSRV_HAP_SMART);
+ /*
+ * ARM9 caches are tagged with virtual pages, not physical. As we are going to
+ * share this memory in different address spaces, we don't want it to be cached.
+ * ARM11 has physical tagging, so we can cache this memory without fear of virtual
+ * address aliasing in the TLB, as long as the kernel supports cache colouring for
+ * VIPT architectures.
+ */
+ ui32MappingFlags &= ~PVRSRV_HAP_CACHED;
#endif
psLinuxMemArea = NewIORemapLinuxMemArea(BasePAddr, ui32Bytes, ui32MappingFlags);
if(!psLinuxMemArea)
@@ -1389,6 +1967,16 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
return PVRSRV_ERROR_INVALID_FLAGS;
}
+ /*
+ In case of sparse mapping we need to handle back to the BM as it
+ knows the mapping info
+ */
+ if (ui32MappingFlags & PVRSRV_MEM_SPARSE)
+ {
+ PVR_ASSERT(hBMHandle != IMG_NULL);
+ psLinuxMemArea->hBMHandle = hBMHandle;
+ }
+
*phOSMemHandle = (IMG_HANDLE)psLinuxMemArea;
*ppvCpuVAddr = LinuxMemAreaToCpuVAddr(psLinuxMemArea);
@@ -1397,6 +1985,12 @@ OSReservePhys(IMG_CPU_PHYADDR BasePAddr,
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+ @Function OSUnReservePhys
+ @Description UnRegisters physical memory for user mode mapping
+ @Return TRUE on success, else FALSE
+******************************************************************************/
PVRSRV_ERROR
OSUnReservePhys(IMG_VOID *pvCpuVAddr,
IMG_UINT32 ui32Bytes,
@@ -1441,6 +2035,14 @@ OSUnReservePhys(IMG_VOID *pvCpuVAddr,
}
+/*!
+******************************************************************************
+ @Function OSBaseAllocContigMemory
+ @Description Allocate a block of contiguous virtual non-paged memory.
+ @Input ui32Size - number of bytes to allocate
+ @Output ppvLinAddr - pointer to variable that will receive the linear address of buffer
+ @Return PVRSRV_OK if allocation successed else returns PVRSRV_ERROR_OUT_OF_MEMORY
+ **************************************************************************/
PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLinAddr, IMG_CPU_PHYADDR *psPhysAddr)
{
#if !defined(NO_HARDWARE)
@@ -1451,6 +2053,13 @@ PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLi
return PVRSRV_ERROR_OUT_OF_MEMORY;
#else
+/*
+ * On Linux, the returned virtual address should be used for CPU access,
+ * and not be remapped into the CPU virtual address using ioremap. The fact
+ * that the RAM is being managed by the kernel, and already has a virtual
+ * address, seems to lead to problems when the attributes of the memory are
+ * changed in the ioremap call (such as from cached to non-cached).
+ */
IMG_VOID *pvKernLinAddr;
#if defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
@@ -1468,10 +2077,16 @@ PVRSRV_ERROR OSBaseAllocContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR *pvLi
psPhysAddr->uiAddr = virt_to_phys(pvKernLinAddr);
return PVRSRV_OK;
-#endif
+#endif /* !defined(NO_HARDWARE) */
}
+/*!
+******************************************************************************
+ @Function OSBaseFreeContigMemory
+ @Description Frees memory allocated with OSBaseAllocContigMemory
+ @Input LinAddr - pointer to buffer allocated with OSBaseAllocContigMemory
+ **************************************************************************/
PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinAddr, IMG_CPU_PHYADDR psPhysAddr)
{
#if !defined(NO_HARDWARE)
@@ -1489,6 +2104,25 @@ PVRSRV_ERROR OSBaseFreeContigMemory(IMG_UINT32 ui32Size, IMG_CPU_VIRTADDR pvLinA
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSWriteHWReg
+
+ @Description
+
+ register access function
+
+ @input pvLinRegBaseAddr : lin addr of register block base
+
+ @input ui32Offset :
+
+ @input ui32Value :
+
+ @Return none
+
+******************************************************************************/
+
IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset)
{
#if !defined(NO_HARDWARE)
@@ -1509,6 +2143,22 @@ IMG_VOID OSWriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UIN
#if defined(CONFIG_PCI) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14))
+/*!
+******************************************************************************
+
+ @Function OSPCISetDev
+
+ @Description
+
+ Set a PCI device for subsequent use.
+
+ @input pvPCICookie : Pointer to OS specific PCI structure/cookie
+
+ @input eFlags : Flags
+
+ @Return Pointer to PCI device handle
+
+******************************************************************************/
PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFlags)
{
int err;
@@ -1534,26 +2184,26 @@ PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFl
return IMG_NULL;
}
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
{
pci_set_master(psPVRPCI->psPCIDev);
}
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */
{
#if defined(CONFIG_PCI_MSI)
err = pci_enable_msi(psPVRPCI->psPCIDev);
if (err != 0)
{
PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: Couldn't enable MSI (%d)", err));
- psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI;
+ psPVRPCI->ePCIFlags &= ~HOST_PCI_INIT_FLAG_MSI; /* PRQA S 1474,3358,4130 */ /* misuse of enums */
}
#else
PVR_DPF((PVR_DBG_WARNING, "OSPCISetDev: MSI support not enabled in the kernel"));
#endif
}
-
+ /* Initialise the PCI resource tracking array */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
psPVRPCI->abPCIResourceInUse[i] = IMG_FALSE;
@@ -1562,6 +2212,24 @@ PVRSRV_PCI_DEV_HANDLE OSPCISetDev(IMG_VOID *pvPCICookie, HOST_PCI_INIT_FLAGS eFl
return (PVRSRV_PCI_DEV_HANDLE)psPVRPCI;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAcquireDev
+
+ @Description
+
+ Acquire a PCI device for subsequent use.
+
+ @input ui16VendorID : Vendor PCI ID
+
+ @input ui16VendorID : Device PCI ID
+
+ @input eFlags : Flags
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16DeviceID, HOST_PCI_INIT_FLAGS eFlags)
{
struct pci_dev *psPCIDev;
@@ -1576,6 +2244,22 @@ PVRSRV_PCI_DEV_HANDLE OSPCIAcquireDev(IMG_UINT16 ui16VendorID, IMG_UINT16 ui16De
return OSPCISetDev((IMG_VOID *)psPCIDev, eFlags);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIIRQ
+
+ @Description
+
+ Get the interrupt number for the device.
+
+ @input hPVRPCI : PCI device handle
+
+ @input pui32IRQ : Pointer to where the interrupt number should be returned
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
@@ -1585,6 +2269,7 @@ PVRSRV_ERROR OSPCIIRQ(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 *pui32IRQ)
return PVRSRV_OK;
}
+/* Functions supported by OSPCIAddrRangeFunc */
enum HOST_PCI_ADDR_RANGE_FUNC
{
HOST_PCI_ADDR_RANGE_FUNC_LEN,
@@ -1594,6 +2279,24 @@ enum HOST_PCI_ADDR_RANGE_FUNC
HOST_PCI_ADDR_RANGE_FUNC_RELEASE
};
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeFunc
+
+ @Description
+
+ Internal support function for various address range related functions
+
+ @input eFunc : Function to perform
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return function dependent
+
+******************************************************************************/
static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
PVRSRV_PCI_DEV_HANDLE hPVRPCI,
IMG_UINT32 ui32Index)
@@ -1643,32 +2346,126 @@ static IMG_UINT32 OSPCIAddrRangeFunc(enum HOST_PCI_ADDR_RANGE_FUNC eFunc,
return 0;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeLen
+
+ @Description
+
+ Returns length of a given address range length
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return Length of address range, or 0 if no such range
+
+******************************************************************************/
IMG_UINT32 OSPCIAddrRangeLen(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_LEN, hPVRPCI, ui32Index);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeStart
+
+ @Description
+
+ Returns the start of a given address range
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return Start of address range, or 0 if no such range
+
+******************************************************************************/
IMG_UINT32 OSPCIAddrRangeStart(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_START, hPVRPCI, ui32Index);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIAddrRangeEnd
+
+ @Description
+
+ Returns the end of a given address range
+
+ @input hPVRPCI : PCI device handle"ayy
+
+ @input ui32Index : Address range index
+
+ @Return End of address range, or 0 if no such range
+
+******************************************************************************/
IMG_UINT32 OSPCIAddrRangeEnd(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_END, hPVRPCI, ui32Index);
}
+/*!
+******************************************************************************
+
+ @Function OSPCIRequestAddrRange
+
+ @Description
+
+ Request a given address range index for subsequent use
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIRequestAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI,
IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_REQUEST, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIReleaseAddrRange
+
+ @Description
+
+ Release a given address range that is no longer being used
+
+ @input hPVRPCI : PCI device handle
+
+ @input ui32Index : Address range index
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIReleaseAddrRange(PVRSRV_PCI_DEV_HANDLE hPVRPCI, IMG_UINT32 ui32Index)
{
return OSPCIAddrRangeFunc(HOST_PCI_ADDR_RANGE_FUNC_RELEASE, hPVRPCI, ui32Index) == 0 ? PVRSRV_ERROR_PCI_CALL_FAILED : PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIReleaseDev
+
+ @Description
+
+ Release a PCI device that is no longer being used
+
+ @input hPVRPCI : PCI device handle
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
@@ -1676,7 +2473,7 @@ PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
PVR_TRACE(("OSPCIReleaseDev"));
-
+ /* Release all PCI regions that are currently in use */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
if (psPVRPCI->abPCIResourceInUse[i])
@@ -1688,14 +2485,14 @@ PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
}
#if defined(CONFIG_PCI_MSI)
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_MSI) /* PRQA S 3358 */ /* misuse of enums */
{
pci_disable_msi(psPVRPCI->psPCIDev);
}
#endif
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29))
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
{
pci_clear_master(psPVRPCI->psPCIDev);
}
@@ -1703,11 +2500,25 @@ PVRSRV_ERROR OSPCIReleaseDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
pci_disable_device(psPVRPCI->psPCIDev);
OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psPVRPCI), (IMG_VOID *)psPVRPCI, IMG_NULL);
-
+ /*not nulling pointer, copy on stack*/
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCISuspendDev
+
+ @Description
+
+ Prepare PCI device to be turned off by power management
+
+ @input hPVRPCI : PCI device handle
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
@@ -1716,7 +2527,7 @@ PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
PVR_TRACE(("OSPCISuspendDev"));
-
+ /* Release all PCI regions that are currently in use */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
if (psPVRPCI->abPCIResourceInUse[i])
@@ -1753,6 +2564,24 @@ PVRSRV_ERROR OSPCISuspendDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSPCIResumeDev
+
+ @Description
+
+ Prepare a PCI device to be resumed by power management
+
+ @input hPVRPCI : PCI device handle
+
+ @input pvPCICookie : Pointer to OS specific PCI structure/cookie
+
+ @input eFlags : Flags
+
+ @Return PVESRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
{
PVR_PCI_DEV *psPVRPCI = (PVR_PCI_DEV *)hPVRPCI;
@@ -1795,10 +2624,10 @@ PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
return PVRSRV_ERROR_PCI_CALL_FAILED;
}
- if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER)
+ if (psPVRPCI->ePCIFlags & HOST_PCI_INIT_FLAG_BUS_MASTER) /* PRQA S 3358 */ /* misuse of enums */
pci_set_master(psPVRPCI->psPCIDev);
-
+ /* Restore the PCI resource tracking array */
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++)
{
if (psPVRPCI->abPCIResourceInUse[i])
@@ -1815,10 +2644,11 @@ PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI)
return PVRSRV_OK;
}
-#endif
+#endif /* #if defined(CONFIG_PCI) && (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)) */
#define OS_MAX_TIMERS 8
+/* Timer callback strucure used by OSAddTimer */
typedef struct TIMER_CALLBACK_DATA_TAG
{
IMG_BOOL bInUse;
@@ -1842,9 +2672,11 @@ static TIMER_CALLBACK_DATA sTimers[OS_MAX_TIMERS];
DEFINE_MUTEX(sTimerStructLock);
#else
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to sTimers */
+/* PRQA S 0671,0685 1 */ /* C99 macro not understood by QAC */
static spinlock_t sTimerStructLock = SPIN_LOCK_UNLOCKED;
#else
-static spinlock_t sTimerStructLock = __SPIN_LOCK_UNLOCKED(sTimerStructLock);
+static DEFINE_SPINLOCK(sTimerStructLock);
#endif
#endif
@@ -1853,14 +2685,28 @@ static void OSTimerCallbackBody(TIMER_CALLBACK_DATA *psTimerCBData)
if (!psTimerCBData->bActive)
return;
-
+ /* call timer callback */
psTimerCBData->pfnTimerFunc(psTimerCBData->pvData);
-
+ /* reset timer */
mod_timer(&psTimerCBData->sTimer, psTimerCBData->ui32Delay + jiffies);
}
+/*!
+******************************************************************************
+
+ @Function OSTimerCallbackWrapper
+
+ @Description
+
+ OS specific timer callback wrapper function
+
+ @Input ui32Data : timer callback data
+
+ @Return NONE
+
+******************************************************************************/
static IMG_VOID OSTimerCallbackWrapper(IMG_UINT32 ui32Data)
{
TIMER_CALLBACK_DATA *psTimerCBData = (TIMER_CALLBACK_DATA*)ui32Data;
@@ -1892,6 +2738,24 @@ static void OSTimerWorkQueueCallBack(struct work_struct *psWork)
}
#endif
+/*!
+******************************************************************************
+
+ @Function OSAddTimer
+
+ @Description
+
+ OS specific function to install a timer callback
+
+ @Input pfnTimerFunc : timer callback
+
+ @Input *pvData :callback data
+
+ @Input ui32MsTimeout: callback period
+
+ @Return IMG_HANDLE : valid handle success, NULL failure
+
+******************************************************************************/
IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32 ui32MsTimeout)
{
TIMER_CALLBACK_DATA *psTimerCBData;
@@ -1900,14 +2764,14 @@ IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32
unsigned long ulLockFlags;
#endif
-
+ /* check callback */
if(!pfnTimerFunc)
{
PVR_DPF((PVR_DBG_ERROR, "OSAddTimer: passed invalid callback"));
return IMG_NULL;
}
-
+ /* Allocate timer callback data structure */
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES) || defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
mutex_lock(&sTimerStructLock);
#else
@@ -1937,17 +2801,19 @@ IMG_HANDLE OSAddTimer(PFN_TIMER_FUNC pfnTimerFunc, IMG_VOID *pvData, IMG_UINT32
psTimerCBData->pvData = pvData;
psTimerCBData->bActive = IMG_FALSE;
-
-
-
+ /*
+ HZ = ticks per second
+ ui32MsTimeout = required ms delay
+ ticks = (Hz * ui32MsTimeout) / 1000
+ */
psTimerCBData->ui32Delay = ((HZ * ui32MsTimeout) < 1000)
? 1
: ((HZ * ui32MsTimeout) / 1000);
-
+ /* initialise object */
init_timer(&psTimerCBData->sTimer);
-
-
+ /* setup timer object */
+ /* PRQA S 0307,0563 1 */ /* ignore warning about inconpartible ptr casting */
psTimerCBData->sTimer.function = (IMG_VOID *)OSTimerCallbackWrapper;
psTimerCBData->sTimer.data = (IMG_UINT32)psTimerCBData;
@@ -1964,6 +2830,20 @@ static inline TIMER_CALLBACK_DATA *GetTimerStructure(IMG_HANDLE hTimer)
return &sTimers[ui32i];
}
+/*!
+******************************************************************************
+
+ @Function OSRemoveTimer
+
+ @Description
+
+ OS specific function to remove a timer callback
+
+ @Input hTimer : timer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
{
TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
@@ -1971,13 +2851,27 @@ PVRSRV_ERROR OSRemoveTimer (IMG_HANDLE hTimer)
PVR_ASSERT(psTimerCBData->bInUse);
PVR_ASSERT(!psTimerCBData->bActive);
-
+ /* free timer callback data struct */
psTimerCBData->bInUse = IMG_FALSE;
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSEnableTimer
+
+ @Description
+
+ OS specific function to enable a timer callback
+
+ @Input hTimer : timer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
{
TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
@@ -1985,19 +2879,33 @@ PVRSRV_ERROR OSEnableTimer (IMG_HANDLE hTimer)
PVR_ASSERT(psTimerCBData->bInUse);
PVR_ASSERT(!psTimerCBData->bActive);
-
+ /* Start timer arming */
psTimerCBData->bActive = IMG_TRUE;
-
+ /* set the expire time */
psTimerCBData->sTimer.expires = psTimerCBData->ui32Delay + jiffies;
-
+ /* Add the timer to the list */
add_timer(&psTimerCBData->sTimer);
return PVRSRV_OK;
}
+/*!
+******************************************************************************
+
+ @Function OSDisableTimer
+
+ @Description
+
+ OS specific function to disable a timer callback
+
+ @Input hTimer : timer handle
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
{
TIMER_CALLBACK_DATA *psTimerCBData = GetTimerStructure(hTimer);
@@ -2005,7 +2913,7 @@ PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
PVR_ASSERT(psTimerCBData->bInUse);
PVR_ASSERT(psTimerCBData->bActive);
-
+ /* Stop timer from arming */
psTimerCBData->bActive = IMG_FALSE;
smp_mb();
@@ -2016,11 +2924,17 @@ PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
flush_scheduled_work();
#endif
-
+ /* remove timer */
del_timer_sync(&psTimerCBData->sTimer);
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
-
+ /*
+ * This second flush is to catch the case where the timer ran
+ * before we managed to delete it, in which case, it will have
+ * queued more work for the workqueue. Since the bActive flag
+ * has been cleared, this second flush won't result in the
+ * timer being rearmed.
+ */
flush_workqueue(psTimerWorkQueue);
#endif
#if defined(PVR_LINUX_TIMERS_USING_SHARED_WORKQUEUE)
@@ -2031,6 +2945,22 @@ PVRSRV_ERROR OSDisableTimer (IMG_HANDLE hTimer)
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectCreateKM
+
+ @Description
+
+ OS specific function to create an event object
+
+ @Input pszName : Globally unique event object name (if null name must be autogenerated)
+
+ @Output psEventObject : OS event object info structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT_KM *psEventObject)
#else
@@ -2044,12 +2974,12 @@ PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *
{
if(pszName)
{
-
+ /* copy over the event object name */
strncpy(psEventObject->szName, pszName, EVENTOBJNAME_MAXLENGTH);
}
else
{
-
+ /* autogenerate a name */
static IMG_UINT16 ui16NameIndex = 0;
#if defined (SUPPORT_SID_INTERFACE)
snprintf(psEventObject->szName, EVENTOBJNAME_MAXLENGTH, "PVRSRV_EVENTOBJECT_KM_%d", ui16NameIndex++);
@@ -2075,6 +3005,20 @@ PVRSRV_ERROR OSEventObjectCreateKM(const IMG_CHAR *pszName, PVRSRV_EVENTOBJECT *
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectDestroyKM
+
+ @Description
+
+ OS specific function to destroy an event object
+
+ @Input psEventObject : OS event object info structure
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT_KM *psEventObject)
#else
@@ -2104,6 +3048,20 @@ PVRSRV_ERROR OSEventObjectDestroyKM(PVRSRV_EVENTOBJECT *psEventObject)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectWaitKM
+
+ @Description
+
+ OS specific function to wait for an event object. Called from client
+
+ @Input hOSEventKM : OS and kernel specific handle to event object
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM)
{
PVRSRV_ERROR eError;
@@ -2121,6 +3079,21 @@ PVRSRV_ERROR OSEventObjectWaitKM(IMG_HANDLE hOSEventKM)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectOpenKM
+
+ @Description
+
+ OS specific function to open an event object. Called from client
+
+ @Input psEventObject : Pointer to an event object
+ @Output phOSEvent : OS and kernel specific handle to event object
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
#else
@@ -2148,6 +3121,22 @@ PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectCloseKM
+
+ @Description
+
+ OS specific function to close an event object. Called from client
+
+ @Input psEventObject : Pointer to an event object
+ @OInput hOSEventKM : OS and kernel specific handle to event object
+
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
#if defined (SUPPORT_SID_INTERFACE)
PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT_KM *psEventObject,
#else
@@ -2176,6 +3165,20 @@ PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
}
+/*!
+******************************************************************************
+
+ @Function OSEventObjectSignalKM
+
+ @Description
+
+ OS specific function to 'signal' an event object. Called from L/MISR
+
+ @Input hOSEventKM : OS and kernel specific handle to event object
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM)
{
PVRSRV_ERROR eError;
@@ -2193,11 +3196,43 @@ PVRSRV_ERROR OSEventObjectSignalKM(IMG_HANDLE hOSEventKM)
return eError;
}
+/*!
+******************************************************************************
+
+ @Function OSProcHasPrivSrvInit
+
+ @Description
+
+ Does the process have sufficient privileges to initialise services?
+
+ @Input none
+
+ @Return IMG_BOOL :
+
+******************************************************************************/
IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID)
{
return (capable(CAP_SYS_MODULE) != 0) ? IMG_TRUE : IMG_FALSE;
}
+/*!
+******************************************************************************
+
+ @Function OSCopyToUser
+
+ @Description
+
+ Copy a block of data into user space
+
+ @Input pvSrc
+
+ @Output pvDest
+
+ @Input ui32Bytes
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
IMG_VOID *pvDest,
IMG_VOID *pvSrc,
@@ -2211,6 +3246,24 @@ PVRSRV_ERROR OSCopyToUser(IMG_PVOID pvProcess,
return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function OSCopyFromUser
+
+ @Description
+
+ Copy a block of data from the user space
+
+ @Output pvDest
+
+ @Input pvSrc
+
+ @Input ui32Bytes
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
IMG_VOID *pvDest,
IMG_VOID *pvSrc,
@@ -2224,6 +3277,24 @@ PVRSRV_ERROR OSCopyFromUser( IMG_PVOID pvProcess,
return PVRSRV_ERROR_FAILED_TO_COPY_VIRT_MEMORY;
}
+/*!
+******************************************************************************
+
+ @Function OSAccessOK
+
+ @Description
+
+ Checks if a user space pointer is valide
+
+ @Input eVerification
+
+ @Input pvUserPtr
+
+ @Input ui32Bytes
+
+ @Return IMG_BOOL :
+
+******************************************************************************/
IMG_BOOL OSAccessOK(IMG_VERIFY_TEST eVerification, IMG_VOID *pvUserPtr, IMG_UINT32 ui32Bytes)
{
IMG_INT linuxType;
@@ -2264,6 +3335,28 @@ typedef struct _sWrapMemInfo_
} sWrapMemInfo;
+/*!
+******************************************************************************
+
+ @Function *CPUVAddrToPFN
+
+ @Description
+
+ Find the PFN associated with a given CPU virtual address, and return
+ the associated page structure, if it exists.
+ The page in question must be present (i.e. no fault handling required),
+ and must be writable. A get_page is done on the returned page structure.
+
+ @Input psVMArea - pointer to VM area structure
+ ulCPUVAddr - CPU virtual address
+ pulPFN - Pointer to returned PFN.
+ ppsPAge - Pointer to returned page structure pointer.
+
+ @Output *pulPFN - Set to PFN
+ *ppsPage - Pointer to the page structure if present, else NULL.
+ @Return IMG_TRUE if PFN lookup was succesful.
+
+******************************************************************************/
static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUVAddr, IMG_UINT32 *pulPFN, struct page **ppsPage)
{
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,10))
@@ -2313,6 +3406,20 @@ static IMG_BOOL CPUVAddrToPFN(struct vm_area_struct *psVMArea, IMG_UINT32 ulCPUV
#endif
}
+/*!
+******************************************************************************
+
+ @Function OSReleasePhysPageAddr
+
+ @Description
+
+ Release wrapped memory.
+
+ @Input hOSWrapMem : Driver cookie
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
{
sWrapMemInfo *psInfo = (sWrapMemInfo *)hOSWrapMem;
@@ -2341,7 +3448,12 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
PVR_ASSERT(psPage != NULL);
-
+ /*
+ * If the number of pages mapped is not the same as
+ * the number of pages in the address range, then
+ * get_user_pages must have failed, so we are cleaning
+ * up after failure, and the pages can't be dirty.
+ */
if (psInfo->iNumPagesMapped == psInfo->iNumPages)
{
if (!PageReserved(psPage))
@@ -2387,6 +3499,59 @@ PVRSRV_ERROR OSReleasePhysPageAddr(IMG_HANDLE hOSWrapMem)
return PVRSRV_OK;
}
+#if defined(CONFIG_TI_TILER)
+
+static IMG_UINT32 CPUAddrToTilerPhy(IMG_UINT32 uiAddr)
+{
+ IMG_UINT32 ui32PhysAddr = 0;
+ pte_t *ptep, pte;
+ pgd_t *pgd;
+ pmd_t *pmd;
+
+ pgd = pgd_offset(current->mm, uiAddr);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ goto err_out;
+
+ pmd = pmd_offset(pgd, uiAddr);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ goto err_out;
+
+ ptep = pte_offset_map(pmd, uiAddr);
+ if (!ptep)
+ goto err_out;
+
+ pte = *ptep;
+ if (!pte_present(pte))
+ goto err_out;
+
+ ui32PhysAddr = (pte & PAGE_MASK) | (~PAGE_MASK & uiAddr);
+
+ /* If the physAddr is not in the TILER physical range
+ * then we don't proceed.
+ */
+ if (ui32PhysAddr < 0x60000000 && ui32PhysAddr > 0x7fffffff)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "CPUAddrToTilerPhy: Not in tiler range"));
+ ui32PhysAddr = 0;
+ goto err_out;
+ }
+
+err_out:
+ return ui32PhysAddr;
+}
+
+#endif /* defined(CONFIG_TI_TILER) */
+
+/*!
+******************************************************************************
+
+ @Function OSAcquirePhysPageAddr
+
+ @Description
+
+ @Return PVRSRV_ERROR
+
+******************************************************************************/
PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
IMG_UINT32 ui32Bytes,
IMG_SYS_PHYADDR *psSysPAddr,
@@ -2404,16 +3569,18 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
sWrapMemInfo *psInfo = NULL;
IMG_BOOL bHavePageStructs = IMG_FALSE;
IMG_BOOL bHaveNoPageStructs = IMG_FALSE;
- IMG_BOOL bPFNMismatch = IMG_FALSE;
IMG_BOOL bMMapSemHeld = IMG_FALSE;
PVRSRV_ERROR eError = PVRSRV_ERROR_OUT_OF_MEMORY;
-
+ /* Align start and end addresses to page boundaries */
ulStartAddr = ulStartAddrOrig & PAGE_MASK;
ulBeyondEndAddr = PAGE_ALIGN(ulBeyondEndAddrOrig);
ulAddrRange = ulBeyondEndAddr - ulStartAddr;
-
+ /*
+ * Check for address range calculation overflow, and attempts to wrap
+ * zero bytes.
+ */
if (ulBeyondEndAddr <= ulStartAddr)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -2422,7 +3589,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
-
+ /* Allocate information structure */
psInfo = kmalloc(sizeof(*psInfo), GFP_KERNEL);
if (psInfo == NULL)
{
@@ -2440,7 +3607,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
psInfo->iNumPages = (IMG_INT)(ulAddrRange >> PAGE_SHIFT);
psInfo->iPageOffset = (IMG_INT)(ulStartAddrOrig & ~PAGE_MASK);
-
+ /* Allocate physical address array */
psInfo->psPhysAddr = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr), GFP_KERNEL);
if (psInfo->psPhysAddr == NULL)
{
@@ -2450,7 +3617,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
}
memset(psInfo->psPhysAddr, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->psPhysAddr));
-
+ /* Allocate page array */
psInfo->ppsPages = kmalloc((size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages), GFP_KERNEL);
if (psInfo->ppsPages == NULL)
{
@@ -2460,22 +3627,22 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
}
memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
-
+ /* Default error code from now on */
eError = PVRSRV_ERROR_BAD_MAPPING;
-
+ /* Set the mapping type to aid clean up */
psInfo->eType = WRAP_TYPE_GET_USER_PAGES;
-
+ /* Lock down user memory */
down_read(&current->mm->mmap_sem);
bMMapSemHeld = IMG_TRUE;
-
+ /* Get page list */
psInfo->iNumPagesMapped = get_user_pages(current, current->mm, ulStartAddr, psInfo->iNumPages, 1, 0, psInfo->ppsPages, NULL);
if (psInfo->iNumPagesMapped >= 0)
{
-
+ /* See if we got all the pages we wanted */
if (psInfo->iNumPagesMapped != psInfo->iNumPages)
{
PVR_TRACE(("OSAcquirePhysPageAddr: Couldn't map all the pages needed (wanted: %d, got %d)", psInfo->iNumPages, psInfo->iNumPagesMapped));
@@ -2483,7 +3650,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
-
+ /* Build list of physical page addresses */
for (i = 0; i < psInfo->iNumPages; i++)
{
IMG_CPU_PHYADDR CPUPhysAddr;
@@ -2508,13 +3675,18 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
PVR_DPF((PVR_DBG_MESSAGE, "OSAcquirePhysPageAddr: get_user_pages failed (%d), using CPU page table", psInfo->iNumPagesMapped));
-
+ /* Reset some fields */
psInfo->eType = WRAP_TYPE_NULL;
psInfo->iNumPagesMapped = 0;
memset(psInfo->ppsPages, 0, (size_t)psInfo->iNumPages * sizeof(*psInfo->ppsPages));
-
-
+ /*
+ * get_user_pages didn't work. If this is due to the address range
+ * representing memory mapped I/O, then we'll look for the pages
+ * in the appropriate memory region of the process.
+ */
+
+ /* Set the mapping type to aid clean up */
psInfo->eType = WRAP_TYPE_FIND_VMA;
psVMArea = find_vma(current->mm, ulStartAddrOrig);
@@ -2529,7 +3701,10 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
psInfo->psVMArea = psVMArea;
#endif
-
+ /*
+ * find_vma locates a region with an end point past a given
+ * virtual address. So check the address is actually in the region.
+ */
if (ulStartAddrOrig < psVMArea->vm_start)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -2537,7 +3712,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
-
+ /* Now check the end address is in range */
if (ulBeyondEndAddrOrig > psVMArea->vm_end)
{
PVR_DPF((PVR_DBG_ERROR,
@@ -2545,7 +3720,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
-
+ /* Does the region represent memory mapped I/O? */
if ((psVMArea->vm_flags & (VM_IO | VM_RESERVED)) != (VM_IO | VM_RESERVED))
{
PVR_DPF((PVR_DBG_ERROR,
@@ -2553,7 +3728,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
-
+ /* We require read and write access */
if ((psVMArea->vm_flags & (VM_READ | VM_WRITE)) != (VM_READ | VM_WRITE))
{
PVR_DPF((PVR_DBG_ERROR,
@@ -2577,20 +3752,20 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
}
if (psInfo->ppsPages[i] == NULL)
{
+#if defined(CONFIG_TI_TILER)
+ /* This could be tiler memory.*/
+ IMG_UINT32 ui32TilerAddr = CPUAddrToTilerPhy(ulAddr);
+ if (ui32TilerAddr)
+ {
+ bHavePageStructs = IMG_TRUE;
+ psInfo->iNumPagesMapped++;
+ psInfo->psPhysAddr[i].uiAddr = ui32TilerAddr;
+ psSysPAddr[i].uiAddr = ui32TilerAddr;
+ continue;
+ }
+#endif /* defined(CONFIG_TI_TILER) */
bHaveNoPageStructs = IMG_TRUE;
-
-#if defined(VM_PFNMAP)
- if ((psVMArea->vm_flags & VM_PFNMAP) != 0)
- {
- IMG_UINT32 ulPFNRaw = ((ulAddr - psVMArea->vm_start) >> PAGE_SHIFT) + psVMArea->vm_pgoff;
-
- if (ulPFNRaw != ulPFN)
- {
- bPFNMismatch = IMG_TRUE;
- }
- }
-#endif
}
else
{
@@ -2631,7 +3806,7 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
if (!bHaveNoPageStructs)
{
-
+ /* The ideal case; every page has a page structure */
goto exit;
}
@@ -2644,34 +3819,21 @@ PVRSRV_ERROR OSAcquirePhysPageAddr(IMG_VOID *pvCPUVAddr,
goto error;
}
- if (bPFNMismatch)
- {
- PVR_DPF((PVR_DBG_ERROR,
- "OSAcquirePhysPageAddr: PFN calculation mismatch for VM_PFNMAP region"));
- goto error;
- }
-
exit:
PVR_ASSERT(bMMapSemHeld);
up_read(&current->mm->mmap_sem);
-
+ /* Return the cookie */
*phOSWrapMem = (IMG_HANDLE)psInfo;
if (bHaveNoPageStructs)
{
- PVR_DPF((PVR_DBG_WARNING,
+ PVR_DPF((PVR_DBG_MESSAGE,
"OSAcquirePhysPageAddr: Region contains pages which can't be locked down (no page structures)"));
}
PVR_ASSERT(psInfo->eType != 0);
-#if 0
-
-
- OSCleanCPUCacheRangeKM(pvCPUVAddr, (IMG_VOID *)((IMG_CHAR *)pvCPUVAddr + ui32Bytes));
-#endif
-
return PVRSRV_OK;
error:
@@ -2687,52 +3849,96 @@ error:
}
typedef void (*InnerCacheOp_t)(const void *pvStart, const void *pvEnd);
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
-typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
+
+#if defined(__arm__) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,39))
+typedef void (*OuterCacheOp_t)(phys_addr_t uStart, phys_addr_t uEnd);
#else
-typedef void (*OuterCacheOp_t)(phys_addr_t ulStart, phys_addr_t ulEnd);
+typedef void (*OuterCacheOp_t)(unsigned long ulStart, unsigned long ulEnd);
#endif
#if defined(CONFIG_OUTER_CACHE)
-typedef unsigned long (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
+typedef IMG_BOOL (*MemAreaToPhys_t)(LinuxMemArea *psLinuxMemArea,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum);
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart);
-static unsigned long VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum)
+static IMG_BOOL VMallocAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
{
- return vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+ *pulStart = vmalloc_to_pfn(pvRangeAddrStart + ui32PageNum * PAGE_SIZE) << PAGE_SHIFT;
+ return IMG_TRUE;
}
-static unsigned long ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum)
+static IMG_BOOL ExternalKVAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
{
IMG_SYS_PHYADDR SysPAddr;
IMG_CPU_PHYADDR CpuPAddr;
SysPAddr = psLinuxMemArea->uData.sExternalKV.uPhysAddr.pSysPhysAddr[ui32PageNumOffset + ui32PageNum];
CpuPAddr = SysSysPAddrToCpuPAddr(SysPAddr);
- return CpuPAddr.uiAddr;
+ *pulStart = CpuPAddr.uiAddr;
+ return IMG_TRUE;
}
-static unsigned long AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
- IMG_VOID *pvRangeAddrStart,
- IMG_UINT32 ui32PageNumOffset,
- IMG_UINT32 ui32PageNum)
+static IMG_BOOL AllocPagesAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
{
struct page *pPage;
- pPage = psLinuxMemArea->uData.sPageList.pvPageList[ui32PageNumOffset + ui32PageNum];
- return page_to_pfn(pPage) << PAGE_SHIFT;
+
+ pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PageNumOffset + ui32PageNum];
+ *pulStart = page_to_pfn(pPage) << PAGE_SHIFT;
+ return IMG_TRUE;
}
-#endif
+static IMG_BOOL AllocPagesSparseAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
+{
+ IMG_UINT32 ui32VirtOffset = (ui32PageNumOffset + ui32PageNum) << PAGE_SHIFT;
+ IMG_UINT32 ui32PhysOffset;
+ struct page *pPage;
+
+ if (BM_VirtOffsetToPhysical(psLinuxMemArea->hBMHandle, ui32VirtOffset, &ui32PhysOffset))
+ {
+ PVR_ASSERT(ui32PhysOffset <= ui32VirtOffset);
+ pPage = psLinuxMemArea->uData.sPageList.ppsPageList[ui32PhysOffset >> PAGE_SHIFT];
+ *pulStart = page_to_pfn(pPage) << PAGE_SHIFT;
+ return IMG_TRUE;
+ }
+
+ return IMG_FALSE;
+}
+
+
+static IMG_BOOL IONAreaToPhys(LinuxMemArea *psLinuxMemArea,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32PageNumOffset,
+ IMG_UINT32 ui32PageNum,
+ unsigned long *pulStart)
+{
+ IMG_CPU_PHYADDR CpuPAddr;
+ CpuPAddr = psLinuxMemArea->uData.sIONTilerAlloc.pCPUPhysAddrs[ui32PageNumOffset + ui32PageNum];
+ *pulStart = CpuPAddr.uiAddr;
+ return IMG_TRUE;
+}
+
+#endif /* defined(CONFIG_OUTER_CACHE) */
+
+/* g_sMMapMutex must be held while this function is called */
-#ifndef __mips__
static
IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
IMG_VOID *pvRangeAddrStart, IMG_UINT32 ui32Length)
@@ -2740,7 +3946,10 @@ IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
PKV_OFFSET_STRUCT psOffsetStruct;
IMG_VOID *pvMinVAddr;
-
+ /* There's no kernel-virtual for this type of allocation, so if
+ * we're flushing it, it must be user-virtual, and therefore
+ * have a mapping.
+ */
list_for_each_entry(psOffsetStruct, psMMapOffsetStructList, sAreaItem)
{
if(OSGetCurrentProcessIDKM() != psOffsetStruct->ui32PID)
@@ -2748,7 +3957,7 @@ IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
pvMinVAddr = (IMG_VOID *)psOffsetStruct->ui32UserVAddr;
-
+ /* Within permissible range */
if(pvRangeAddrStart >= pvMinVAddr &&
ui32Length <= psOffsetStruct->ui32RealByteSize)
return pvMinVAddr;
@@ -2757,8 +3966,42 @@ IMG_VOID *FindMMapBaseVAddr(struct list_head *psMMapOffsetStructList,
return IMG_NULL;
}
+extern PVRSRV_LINUX_MUTEX g_sMMapMutex;
+
+static inline void DoInnerCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
+ IMG_VOID *pvRangeAddrStart,
+ IMG_UINT32 ui32Length,
+ InnerCacheOp_t pfnInnerCacheOp)
+{
+ LinuxMemArea *psLinuxMemArea = hOSMemHandle;
+
+ if (!psLinuxMemArea->hBMHandle)
+ {
+ pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ }
+ else
+ {
+ IMG_UINT32 ui32ByteRemain = ui32Length;
+ IMG_UINT32 ui32BytesToDo = PAGE_SIZE - (((IMG_UINT32) pvRangeAddrStart) & (~PAGE_MASK));
+ IMG_UINT8 *pbDo = (IMG_UINT8 *) pvRangeAddrStart;
+
+ while(ui32ByteRemain)
+ {
+ if (BM_MapPageAtOffset(psLinuxMemArea->hBMHandle, ui32ByteOffset + (ui32Length - ui32ByteRemain)))
+ {
+ pfnInnerCacheOp(pbDo, pbDo + ui32BytesToDo);
+ }
+ pbDo += ui32BytesToDo;
+ ui32ByteRemain -= ui32BytesToDo;
+ ui32BytesToDo = MIN(ui32ByteRemain, PAGE_SIZE);
+ }
+ }
+}
+
static
IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length,
InnerCacheOp_t pfnInnerCacheOp,
@@ -2776,8 +4019,10 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
PVR_ASSERT(psLinuxMemArea != IMG_NULL);
- ui32AreaLength = psLinuxMemArea->ui32ByteSize;
+ LinuxLockMutex(&g_sMMapMutex);
+
psMMapOffsetStructList = &psLinuxMemArea->sMMapOffsetStructList;
+ ui32AreaLength = psLinuxMemArea->ui32ByteSize;
PVR_ASSERT(ui32Length <= ui32AreaLength);
@@ -2787,7 +4032,7 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
psLinuxMemArea = psLinuxMemArea->uData.sSubAlloc.psParentLinuxMemArea;
}
-
+ /* Recursion surely isn't possible? */
PVR_ASSERT(psLinuxMemArea->eAreaType != LINUX_MEM_AREA_SUB_ALLOC);
switch(psLinuxMemArea->eAreaType)
@@ -2798,63 +4043,84 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
{
pvMinVAddr = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress + ui32AreaOffset;
-
+ /* Outside permissible range */
if(pvRangeAddrStart < pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
}
else
{
-
-
+ /* If this isn't a vmalloc address, assume we're flushing by
+ * user-virtual. Compute the mmap base vaddr and use this to
+ * compute the offset in vmalloc space.
+ */
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
pvRangeAddrStart, ui32Length);
if(!pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
#if defined(CONFIG_OUTER_CACHE)
-
+ /*
+ * We don't need to worry about cache aliasing here because
+ * we have already flushed the virtually-indexed caches (L1
+ * etc.) by the supplied user-virtual addresses.
+ *
+ * The vmalloc address will only be used to determine
+ * affected physical pages for outer cache flushing.
+ */
pvRangeAddrStart = psLinuxMemArea->uData.sVmalloc.pvVmallocAddress +
(ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr);
}
pfnMemAreaToPhys = VMallocAreaToPhys;
-#else
+#else /* defined(CONFIG_OUTER_CACHE) */
}
-#endif
+#endif /* defined(CONFIG_OUTER_CACHE) */
break;
}
case LINUX_MEM_AREA_EXTERNAL_KV:
{
-
+ /* We'll only see bPhysContig for frame buffers, and we shouldn't
+ * be flushing those (they're write combined or uncached).
+ */
if (psLinuxMemArea->uData.sExternalKV.bPhysContig == IMG_TRUE)
{
PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush contiguous external memory", __func__));
-
goto err_blocked;
}
-
+ /* If it has a kernel virtual address, something odd has happened.
+ * We expect EXTERNAL_KV _only_ from the wrapping of ALLOC_PAGES.
+ */
if (psLinuxMemArea->uData.sExternalKV.pvExternalKV != IMG_NULL)
{
PVR_DPF((PVR_DBG_WARNING, "%s: Attempt to flush external memory with a kernel virtual address", __func__));
-
goto err_blocked;
}
-
-
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
pvRangeAddrStart, ui32Length);
if(!pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
#if defined(CONFIG_OUTER_CACHE)
ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
@@ -2863,6 +4129,26 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
break;
}
+ case LINUX_MEM_AREA_ION:
+ {
+ pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
+ pvRangeAddrStart, ui32Length);
+ if(!pvMinVAddr)
+ goto err_blocked;
+
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
+
+#if defined(CONFIG_OUTER_CACHE)
+ ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
+ pfnMemAreaToPhys = IONAreaToPhys;
+#endif
+ break;
+ }
+
case LINUX_MEM_AREA_ALLOC_PAGES:
{
pvMinVAddr = FindMMapBaseVAddr(psMMapOffsetStructList,
@@ -2870,11 +4156,22 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
if(!pvMinVAddr)
goto err_blocked;
- pfnInnerCacheOp(pvRangeAddrStart, pvRangeAddrStart + ui32Length);
+ DoInnerCacheOp(hOSMemHandle,
+ ui32ByteOffset,
+ pvRangeAddrStart,
+ ui32Length,
+ pfnInnerCacheOp);
#if defined(CONFIG_OUTER_CACHE)
ui32PageNumOffset = ((ui32AreaOffset & PAGE_MASK) + (pvRangeAddrStart - pvMinVAddr)) >> PAGE_SHIFT;
- pfnMemAreaToPhys = AllocPagesAreaToPhys;
+ if (psLinuxMemArea->hBMHandle)
+ {
+ pfnMemAreaToPhys = AllocPagesSparseAreaToPhys;
+ }
+ else
+ {
+ pfnMemAreaToPhys = AllocPagesAreaToPhys;
+ }
#endif
break;
}
@@ -2883,35 +4180,41 @@ IMG_BOOL CheckExecuteCacheOp(IMG_HANDLE hOSMemHandle,
PVR_DBG_BREAK;
}
+ LinuxUnLockMutex(&g_sMMapMutex);
+
#if defined(CONFIG_OUTER_CACHE)
PVR_ASSERT(pfnMemAreaToPhys != IMG_NULL);
-
+ /* Outer caches need some more work, to get a list of physical addresses */
{
unsigned long ulStart, ulEnd, ulLength, ulStartOffset, ulEndOffset;
IMG_UINT32 i, ui32NumPages;
+ IMG_BOOL bValidPage;
-
+ /* Length and offsets of flush region WRT page alignment */
ulLength = (unsigned long)ui32Length;
ulStartOffset = ((unsigned long)pvRangeAddrStart) & (PAGE_SIZE - 1);
ulEndOffset = ((unsigned long)pvRangeAddrStart + ulLength) & (PAGE_SIZE - 1);
-
+ /* The affected pages, rounded up */
ui32NumPages = (ulStartOffset + ulLength + PAGE_SIZE - 1) >> PAGE_SHIFT;
for(i = 0; i < ui32NumPages; i++)
{
- ulStart = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
- ui32PageNumOffset, i);
- ulEnd = ulStart + PAGE_SIZE;
-
- if(i == ui32NumPages - 1 && ulEndOffset != 0)
- ulEnd = ulStart + ulEndOffset;
-
- if(i == 0)
- ulStart += ulStartOffset;
-
- pfnOuterCacheOp(ulStart, ulEnd);
+ bValidPage = pfnMemAreaToPhys(psLinuxMemArea, pvRangeAddrStart,
+ ui32PageNumOffset, i, &ulStart);
+ if (bValidPage)
+ {
+ ulEnd = ulStart + PAGE_SIZE;
+
+ if(i == ui32NumPages - 1 && ulEndOffset != 0)
+ ulEnd = ulStart + ulEndOffset;
+
+ if(i == 0)
+ ulStart += ulStartOffset;
+
+ pfnOuterCacheOp(ulStart, ulEnd);
+ }
}
}
#endif
@@ -2923,11 +4226,10 @@ err_blocked:
"%p-%p (type %d)", __func__,
pvRangeAddrStart, pvRangeAddrStart + ui32Length,
psLinuxMemArea->eAreaType));
+ LinuxUnLockMutex(&g_sMMapMutex);
return IMG_FALSE;
}
-#endif
-
#if defined(__i386__)
#define ROUND_UP(x,a) (((x) + (a) - 1) & ~((a) - 1))
@@ -2949,13 +4251,15 @@ static void x86_flush_cache_range(const void *pvStart, const void *pvEnd)
mb();
for(pbBase = pbStart; pbBase < pbEnd; pbBase += boot_cpu_data.x86_clflush_size)
+ {
clflush(pbBase);
+ }
mb();
}
IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
{
-
+ /* No clean feature on x86 */
ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
}
@@ -2965,33 +4269,36 @@ IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
}
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
-
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ /* Write-back and invalidate */
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
x86_flush_cache_range, IMG_NULL);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
-
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ /* No clean feature on x86 */
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
x86_flush_cache_range, IMG_NULL);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
-
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ /* No invalidate-only support */
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset, pvRangeAddrStart, ui32Length,
x86_flush_cache_range, IMG_NULL);
}
-#else
+#else /* defined(__i386__) */
#if defined(__arm__)
@@ -3003,25 +4310,35 @@ static void per_cpu_cache_flush(void *arg)
IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
{
-
+ /* No full (inner) cache clean op */
ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
-#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
- outer_clean_all();
+#if defined(CONFIG_OUTER_CACHE)
+ outer_clean_range(0, ULONG_MAX);
#endif
}
IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
{
ON_EACH_CPU(per_cpu_cache_flush, NULL, 1);
-#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
+#if defined(CONFIG_OUTER_CACHE) && \
+ (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37))
+ /* To use the "deferred flush" (not clean) DDK feature you need a kernel
+ * implementation of outer_flush_all() for ARM CPUs with an outer cache
+ * controller (e.g. PL310, common with Cortex A9 and later).
+ *
+ * Reference DDKs don't require this functionality, as they will only
+ * clean the cache, never flush (clean+invalidate) it.
+ */
outer_flush_all();
#endif
}
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,34))
static inline size_t pvr_dmac_range_len(const void *pvStart, const void *pvEnd)
{
return (size_t)((char *)pvEnd - (char *)pvStart);
}
+#endif
static void pvr_dmac_inv_range(const void *pvStart, const void *pvEnd)
{
@@ -3042,90 +4359,244 @@ static void pvr_dmac_clean_range(const void *pvStart, const void *pvEnd)
}
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
dmac_flush_range, outer_flush_range);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- IMG_BOOL retval = IMG_TRUE;
+ IMG_BOOL retval = IMG_TRUE;
#if defined(CONFIG_OUTER_CACHE) && !defined(PVR_NO_FULL_CACHE_OPS)
if (ui32Length > PVR_FULL_CACHE_OP_THRESHOLD)
OSCleanCPUCacheKM();
else
#endif
{
- retval = CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ retval = CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
pvr_dmac_clean_range, outer_clean_range);
}
return retval;
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- return CheckExecuteCacheOp(hOSMemHandle, pvRangeAddrStart, ui32Length,
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
pvr_dmac_inv_range, outer_inv_range);
}
-#else
+#else /* defined(__arm__) */
#if defined(__mips__)
+/*
+ * dmac cache functions are supposed to be used for dma
+ * memory which comes from dma-able memory. However examining
+ * the implementation of dmac cache functions and experimenting,
+ * can assert that dmac functions are safe to use for high-mem
+ * memory as well for our OS{Clean/Flush/Invalidate}Cache functions
+ *
+ */
+
IMG_VOID OSCleanCPUCacheKM(IMG_VOID)
{
-
+ /* dmac functions flush full cache if size is larger than
+ * p-cache size. This is a workaround for the fact that
+ * __flush_cache_all is not an exported symbol. Please
+ * replace with custom function if available in latest
+ * version of linux being used.
+ * Arbitrary large number (1MB) which should be larger than
+ * mips p-cache sizes for some time in future.
+ * */
dma_cache_wback(0, 0x100000);
}
IMG_VOID OSFlushCPUCacheKM(IMG_VOID)
{
-
+ /* dmac functions flush full cache if size is larger than
+ * p-cache size. This is a workaround for the fact that
+ * __flush_cache_all is not an exported symbol. Please
+ * replace with custom function if available in latest
+ * version of linux being used.
+ * Arbitrary large number (1MB) which should be larger than
+ * mips p-cache sizes for some time in future.
+ * */
dma_cache_wback_inv(0, 0x100000);
}
+static inline IMG_UINT32 pvr_dma_range_len(const void *pvStart, const void *pvEnd)
+{
+ return (IMG_UINT32)((char *)pvEnd - (char *)pvStart);
+}
+
+static void pvr_dma_cache_wback_inv(const void *pvStart, const void *pvEnd)
+{
+ dma_cache_wback_inv((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd));
+}
+
+static void pvr_dma_cache_wback(const void *pvStart, const void *pvEnd)
+{
+ dma_cache_wback((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd));
+}
+
+static void pvr_dma_cache_inv(const void *pvStart, const void *pvEnd)
+{
+ dma_cache_inv((IMG_UINTPTR_T)pvStart, pvr_dma_range_len(pvStart, pvEnd));
+}
+
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- if (ui32Length)
- dma_cache_wback_inv((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
- return IMG_TRUE;
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dma_cache_wback_inv, IMG_NULL);
}
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- if (ui32Length)
- dma_cache_wback((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
- return IMG_TRUE;
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dma_cache_wback, IMG_NULL);
}
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
- if (ui32Length)
- dma_cache_inv((IMG_UINTPTR_T)pvRangeAddrStart, ui32Length);
- return IMG_TRUE;
+ return CheckExecuteCacheOp(hOSMemHandle, ui32ByteOffset,
+ pvRangeAddrStart, ui32Length,
+ pvr_dma_cache_inv, IMG_NULL);
}
-#else
+#else /* defined(__mips__) */
#error "Implement CPU cache flush/clean/invalidate primitives for this CPU!"
-#endif
+#endif /* defined(__mips__) */
+
+#endif /* defined(__arm__) */
+
+#endif /* defined(__i386__) */
+
+typedef struct _AtomicStruct
+{
+ atomic_t RefCount;
+} AtomicStruct;
+
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount)
+{
+ AtomicStruct *psRefCount;
+
+ psRefCount = kmalloc(sizeof(AtomicStruct), GFP_KERNEL);
+ if (psRefCount == NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+ atomic_set(&psRefCount->RefCount, 0);
+
+ *ppvRefCount = psRefCount;
+ return PVRSRV_OK;
+}
+
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ PVR_ASSERT(atomic_read(&psRefCount->RefCount) == 0);
+ kfree(psRefCount);
+}
+
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ atomic_inc(&psRefCount->RefCount);
+}
+
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ return atomic_dec_and_test(&psRefCount->RefCount) ? IMG_TRUE:IMG_FALSE;
+}
+
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount)
+{
+ AtomicStruct *psRefCount = pvRefCount;
+
+ return (IMG_UINT32) atomic_read(&psRefCount->RefCount);
+}
+
+IMG_VOID OSReleaseBridgeLock(IMG_VOID)
+{
+ LinuxUnLockMutex(&gPVRSRVLock);
+}
+
+IMG_VOID OSReacquireBridgeLock(IMG_VOID)
+{
+ LinuxLockMutex(&gPVRSRVLock);
+}
+
+typedef struct _OSTime
+{
+ unsigned long ulTime;
+} OSTime;
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32USOffset)
+{
+ OSTime *psOSTime;
+
+ psOSTime = kmalloc(sizeof(OSTime), GFP_KERNEL);
+ if (psOSTime == IMG_NULL)
+ {
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+
+ psOSTime->ulTime = usecs_to_jiffies(jiffies_to_usecs(jiffies) + ui32USOffset);
+ *pvRet = psOSTime;
+ return PVRSRV_OK;
+}
+
-#endif
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData)
+{
+ OSTime *psOSTime = pvData;
+
+ if (time_is_before_jiffies(psOSTime->ulTime))
+ {
+ return IMG_TRUE;
+ }
+ return IMG_FALSE;
+}
+
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData)
+{
+ kfree(pvData);
+}
-#endif
+IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size)
+{
+ strncpy(pszName, current->comm, MIN(ui32Size,TASK_COMM_LEN));
+}
+/* One time osfunc initialisation */
PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
{
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
@@ -3152,11 +4623,30 @@ PVRSRV_ERROR PVROSFuncInit(IMG_VOID)
}
}
#endif
+
+#if defined (SUPPORT_ION)
+ {
+ PVRSRV_ERROR eError;
+
+ eError = IonInit();
+ if (eError != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: IonInit failed", __FUNCTION__));
+ }
+ }
+#endif
return PVRSRV_OK;
}
+/*
+ * Osfunc deinitialisation.
+ * Note that PVROSFuncInit may not have been called
+ */
IMG_VOID PVROSFuncDeInit(IMG_VOID)
{
+#if defined (SUPPORT_ION)
+ IonDeinit();
+#endif
#if defined(PVR_LINUX_TIMERS_USING_WORKQUEUES)
if (psTimerWorkQueue != NULL)
{
diff --git a/sgx/services4/srvkm/env/linux/osperproc.c b/sgx/services4/srvkm/env/linux/osperproc.c
index 6b57dfc..5116c36 100644
--- a/sgx/services4/srvkm/env/linux/osperproc.c
+++ b/sgx/services4/srvkm/env/linux/osperproc.c
@@ -1,35 +1,55 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux specific per process data functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "osperproc.h"
#include "env_perproc.h"
#include "proc.h"
+#if defined (SUPPORT_ION)
+#include "linux/ion.h"
+extern struct ion_device *psIonDev;
+#endif
extern IMG_UINT32 gui32ReleasePID;
PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
@@ -57,14 +77,28 @@ PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData)
psEnvPerProc->hBlockAlloc = hBlockAlloc;
-
+ /* Linux specific mmap processing */
LinuxMMapPerProcessConnect(psEnvPerProc);
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
-
+ /* Linked list of PVRSRV_FILE_PRIVATE_DATA structures */
INIT_LIST_HEAD(&psEnvPerProc->sDRMAuthListHead);
#endif
-
+#if defined(SUPPORT_ION)
+ OSSNPrintf(psEnvPerProc->azIonClientName, ION_CLIENT_NAME_SIZE, "pvr_ion_client-%d", OSGetCurrentProcessIDKM());
+ psEnvPerProc->psIONClient =
+ ion_client_create(psIonDev,
+ 1 << ION_HEAP_TYPE_SYSTEM_CONTIG |
+ 1 << ION_HEAP_TYPE_SYSTEM,
+ psEnvPerProc->azIonClientName);
+
+ if (IS_ERR_OR_NULL(psEnvPerProc->psIONClient))
+ {
+ PVR_DPF((PVR_DBG_ERROR, "OSPerProcessPrivateDataInit: Couldn't create "
+ "ion client for per process data"));
+ return PVRSRV_ERROR_OUT_OF_MEMORY;
+ }
+#endif /* SUPPORT_ION */
return PVRSRV_OK;
}
@@ -80,17 +114,17 @@ PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData)
psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)hOsPrivateData;
-
+ /* Linux specific mmap processing */
LinuxMMapPerProcessDisconnect(psEnvPerProc);
-
+ /* Remove per process /proc entries */
RemovePerProcessProcDir(psEnvPerProc);
eError = OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_ENV_PER_PROCESS_DATA),
hOsPrivateData,
psEnvPerProc->hBlockAlloc);
-
+ /*not nulling pointer, copy on stack*/
if (eError != PVRSRV_OK)
{
diff --git a/sgx/services4/srvkm/env/linux/pdump.c b/sgx/services4/srvkm/env/linux/pdump.c
index 13d9b0d..192640f 100644
--- a/sgx/services4/srvkm/env/linux/pdump.c
+++ b/sgx/services4/srvkm/env/linux/pdump.c
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Parameter dump macro target routines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if defined (SUPPORT_SGX) || defined (SUPPORT_VGX)
#if defined (PDUMP)
@@ -30,7 +46,7 @@
#include <asm/atomic.h>
#include <stdarg.h>
#if defined (SUPPORT_SGX)
-#include "sgxdefs.h"
+#include "sgxdefs.h" /* Is this still needed? */
#endif
#include "services_headers.h"
@@ -39,14 +55,14 @@
#include "dbgdrvif.h"
#if defined (SUPPORT_SGX)
-#include "sgxmmu.h"
+#include "sgxmmu.h"/* Is this still needed? */
#endif
#include "mm.h"
#include "pdump_km.h"
#include "pdump_int.h"
-#include <linux/kernel.h>
-#include <linux/string.h>
+#include <linux/kernel.h> // sprintf
+#include <linux/string.h> // strncpy, strlen
static IMG_BOOL PDumpWriteString2 (IMG_CHAR * pszString, IMG_UINT32 ui32Flags);
static IMG_BOOL PDumpWriteILock (PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags);
@@ -56,6 +72,9 @@ static IMG_VOID DbgSetMarker (PDBG_STREAM psStream, IMG_UINT32 ui32Marker);
#define PDUMP_DATAMASTER_PIXEL (1)
#define PDUMP_DATAMASTER_EDM (3)
+/*
+ Maximum file size to split output files
+*/
#define MAX_FILE_SIZE 0x40000000
static atomic_t gsPDumpSuspended = ATOMIC_INIT(0);
@@ -87,13 +106,14 @@ static PDBG_PDUMP_STATE gsDBGPdumpState = {{IMG_NULL}, 0, IMG_NULL, IMG_NULL, IM
-IMG_VOID DBGDrvGetServiceTable(IMG_VOID **fn_table);
-
static inline IMG_BOOL PDumpSuspended(IMG_VOID)
{
return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
}
+/*!
+ * \name PDumpOSGetScriptString
+ */
PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
IMG_UINT32 *pui32MaxLen)
{
@@ -106,6 +126,9 @@ PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript,
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSGetMessageString
+ */
PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
IMG_UINT32 *pui32MaxLen)
{
@@ -118,6 +141,9 @@ PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg,
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSGetFilenameString
+ */
PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
IMG_UINT32 *pui32MaxLen)
{
@@ -130,11 +156,17 @@ PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile,
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSWriteString2
+ */
IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags)
{
return PDumpWriteString2(hScript, ui32Flags);
}
+/*!
+ * \name PDumpOSBufprintf
+ */
PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...)
{
IMG_CHAR* pszBuf = hBuf;
@@ -147,7 +179,7 @@ PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG
va_end(vaArgs);
- if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
{
PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
@@ -160,13 +192,16 @@ PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSVSprintf
+ */
PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs)
{
IMG_INT32 n;
n = vsnprintf(pszComment, ui32ScriptSizeMax, pszFormat, vaArgs);
- if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
{
PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
@@ -176,13 +211,19 @@ PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax,
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSDebugPrintf
+ */
IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...)
{
PVR_UNREFERENCED_PARAMETER(pszFormat);
-
+ /* FIXME: Implement using services PVR_DBG or otherwise with kprintf */
}
+/*!
+ * \name PDumpOSSprintf
+ */
PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...)
{
IMG_INT32 n;
@@ -194,7 +235,7 @@ PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax,
va_end(vaArgs);
- if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1)
+ if (n>=(IMG_INT32)ui32ScriptSizeMax || n==-1) /* glibc >= 2.1 or glibc 2.0 */
{
PVR_DPF((PVR_DBG_ERROR, "Buffer overflow detected, pdump output may be incomplete."));
@@ -204,6 +245,9 @@ PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax,
return PVRSRV_OK;
}
+/*!
+ * \name PDumpOSBuflen
+ */
IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
{
IMG_CHAR* pszBuf = hBuffer;
@@ -216,15 +260,18 @@ IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
return(ui32Count);
}
+/*!
+ * \name PDumpOSVerifyLineEnding
+ */
IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax)
{
IMG_UINT32 ui32Count;
IMG_CHAR* pszBuf = hBuffer;
-
+ /* strlen */
ui32Count = PDumpOSBuflen(hBuffer, ui32BufferSizeMax);
-
+ /* Put \r \n sequence at the end if it isn't already there */
if ((ui32Count >= 1) && (pszBuf[ui32Count-1] != '\n') && (ui32Count<ui32BufferSizeMax))
{
pszBuf[ui32Count] = '\n';
@@ -240,22 +287,34 @@ IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMa
}
}
+/*!
+ * \name PDumpOSGetStream
+ */
IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream)
{
return (IMG_HANDLE)gsDBGPdumpState.psStream[ePDumpStream];
}
+/*!
+ * \name PDumpOSGetStreamOffset
+ */
IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream)
{
PDBG_STREAM psStream = gsDBGPdumpState.psStream[ePDumpStream];
return gpfnDbgDrv->pfnGetStreamOffset(psStream);
}
+/*!
+ * \name PDumpOSGetParamFileNum
+ */
IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID)
{
return gsDBGPdumpState.ui32ParamFileNum;
}
+/*!
+ * \name PDumpOSWriteString
+ */
IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
IMG_UINT8 *psui8Data,
IMG_UINT32 ui32Size,
@@ -268,14 +327,21 @@ IMG_BOOL PDumpOSWriteString(IMG_HANDLE hStream,
ui32Flags);
}
+/*!
+ * \name PDumpOSCheckForSplitting
+ */
IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags)
{
-
+ /* File size limit not implemented for this OS.
+ */
PVR_UNREFERENCED_PARAMETER(hStream);
PVR_UNREFERENCED_PARAMETER(ui32Size);
PVR_UNREFERENCED_PARAMETER(ui32Flags);
}
+/*!
+ * \name PDumpOSJTInitialised
+ */
IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
{
if(gpfnDbgDrv)
@@ -285,11 +351,17 @@ IMG_BOOL PDumpOSJTInitialised(IMG_VOID)
return IMG_FALSE;
}
+/*!
+ * \name PDumpOSIsSuspended
+ */
inline IMG_BOOL PDumpOSIsSuspended(IMG_VOID)
{
return (atomic_read(&gsPDumpSuspended) != 0) ? IMG_TRUE : IMG_FALSE;
}
+/*!
+ * \name PDumpOSCPUVAddrToDevPAddr
+ */
IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
@@ -300,19 +372,23 @@ IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_CPU_PHYADDR sCpuPAddr;
PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
- PVR_UNREFERENCED_PARAMETER(ui32PageSize);
+ PVR_UNREFERENCED_PARAMETER(ui32PageSize); /* for when no assert */
-
+ /* Caller must now alway supply hOSMemHandle, even though we only (presently)
+ use it here in the linux implementation */
PVR_ASSERT (hOSMemHandle != IMG_NULL);
sCpuPAddr = OSMemHandleToCpuPAddr(hOSMemHandle, ui32Offset);
PVR_ASSERT((sCpuPAddr.uiAddr & (ui32PageSize - 1)) == 0);
-
+ /* convert CPU physical addr to device physical */
*psDevPAddr = SysCpuPAddrToDevPAddr(eDeviceType, sCpuPAddr);
}
+/*!
+ * \name PDumpOSCPUVAddrToPhysPages
+ */
IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_PUINT8 pui8LinAddr,
@@ -321,7 +397,9 @@ IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
{
if(hOSMemHandle)
{
-
+ /*
+ * If a Services memory handle is provided then use it.
+ */
IMG_CPU_PHYADDR sCpuPAddr;
PVR_UNREFERENCED_PARAMETER(pui8LinAddr);
@@ -338,6 +416,9 @@ IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
}
}
+/*!
+ * \name PDumpOSDebugDriverWrite
+ */
IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
PDUMP_DDWMODE eDbgDrvWriteMode,
IMG_UINT8 *pui8Data,
@@ -365,29 +446,43 @@ IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
return 0xFFFFFFFFU;
}
+/*!
+ * \name PDumpOSReleaseExecution
+ */
IMG_VOID PDumpOSReleaseExecution(IMG_VOID)
{
OSReleaseThreadQuanta();
}
+/**************************************************************************
+ * Function Name : PDumpInit
+ * Outputs : None
+ * Returns :
+ * Description : Reset connection to vldbgdrv
+ * Then try to connect to PDUMP streams
+**************************************************************************/
IMG_VOID PDumpInit(IMG_VOID)
{
IMG_UINT32 i;
DBGKM_CONNECT_NOTIFIER sConnectNotifier;
-
+ /* If we tried this earlier, then we might have connected to the driver
+ * But if pdump.exe was running then the stream connected would fail
+ */
if (!gpfnDbgDrv)
{
- DBGDrvGetServiceTable((IMG_VOID **)&gpfnDbgDrv);
+ DBGDrvGetServiceTable(&gpfnDbgDrv);
-
+ // If something failed then no point in trying to connect streams
if (gpfnDbgDrv == IMG_NULL)
{
return;
}
-
+ /*
+ * Pass the connection notify callback
+ */
sConnectNotifier.pfnConnectNotifier = &PDumpConnectionNotify;
gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
@@ -457,7 +552,9 @@ init_failed:
gsDBGPdumpState.pszMsg = IMG_NULL;
}
-
+ /*
+ * Remove the connection notify callback
+ */
sConnectNotifier.pfnConnectNotifier = 0;
gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
@@ -493,13 +590,22 @@ IMG_VOID PDumpDeInit(IMG_VOID)
gsDBGPdumpState.pszMsg = IMG_NULL;
}
-
+ /*
+ * Remove the connection notify callback
+ */
sConnectNotifier.pfnConnectNotifier = 0;
gpfnDbgDrv->pfnSetConnectNotifier(sConnectNotifier);
gpfnDbgDrv = IMG_NULL;
}
+/**************************************************************************
+ * Function Name : PDumpStartInitPhaseKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : None
+ * Description : Resume init phase state
+**************************************************************************/
PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
{
IMG_UINT32 i;
@@ -515,6 +621,13 @@ PVRSRV_ERROR PDumpStartInitPhaseKM(IMG_VOID)
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpStopInitPhaseKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : None
+ * Description : End init phase state
+**************************************************************************/
PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
{
IMG_UINT32 i;
@@ -531,12 +644,26 @@ PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID)
return PVRSRV_OK;
}
+/**************************************************************************
+ * Function Name : PDumpIsLastCaptureFrameKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : True or false
+ * Description : Tests whether the current frame is being pdumped
+**************************************************************************/
IMG_BOOL PDumpIsLastCaptureFrameKM(IMG_VOID)
{
return gpfnDbgDrv->pfnIsLastCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2]);
}
+/**************************************************************************
+ * Function Name : PDumpIsCaptureFrameKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : True or false
+ * Description : Tests whether the current frame is being pdumped
+**************************************************************************/
IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
{
if (PDumpSuspended())
@@ -546,6 +673,13 @@ IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID)
return gpfnDbgDrv->pfnIsCaptureFrame(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], IMG_FALSE);
}
+/**************************************************************************
+ * Function Name : PDumpSetFrameKM
+ * Inputs : None
+ * Outputs : None
+ * Returns : None
+ * Description : Sets a frame
+**************************************************************************/
PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
{
IMG_UINT32 ui32Stream;
@@ -562,12 +696,30 @@ PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame)
}
+/*****************************************************************************
+ FUNCTION : PDumpWriteString2
+
+ PURPOSE :
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_BOOL PDumpWriteString2(IMG_CHAR * pszString, IMG_UINT32 ui32Flags)
{
return PDumpWriteILock(gsDBGPdumpState.psStream[PDUMP_STREAM_SCRIPT2], (IMG_UINT8 *) pszString, strlen(pszString), ui32Flags);
}
+/*****************************************************************************
+ FUNCTION : PDumpWriteILock
+
+ PURPOSE : Writes, making sure it all goes...
+
+ PARAMETERS :
+
+ RETURNS :
+*****************************************************************************/
static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_UINT32 ui32Count, IMG_UINT32 ui32Flags)
{
IMG_UINT32 ui32Written = 0;
@@ -578,7 +730,9 @@ static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_U
}
-
+ /*
+ Set the stream marker to split output files
+ */
if (psStream == gsDBGPdumpState.psStream[PDUMP_STREAM_PARAM2])
{
@@ -604,11 +758,31 @@ static IMG_BOOL PDumpWriteILock(PDBG_STREAM psStream, IMG_UINT8 *pui8Data, IMG_U
return IMG_TRUE;
}
+/*****************************************************************************
+ FUNCTION : DbgSetFrame
+
+ PURPOSE : Sets the frame in the stream
+
+ PARAMETERS : psStream - Stream pointer
+ ui32Frame - Frame number to set
+
+ RETURNS : None
+*****************************************************************************/
static IMG_VOID DbgSetFrame(PDBG_STREAM psStream, IMG_UINT32 ui32Frame)
{
gpfnDbgDrv->pfnSetFrame(psStream, ui32Frame);
}
+/*****************************************************************************
+ FUNCTION : DbgSetMarker
+
+ PURPOSE : Sets the marker of the stream to split output files
+
+ PARAMETERS : psStream - Stream pointer
+ ui32Marker - Marker number to set
+
+ RETURNS : None
+*****************************************************************************/
static IMG_VOID DbgSetMarker(PDBG_STREAM psStream, IMG_UINT32 ui32Marker)
{
gpfnDbgDrv->pfnSetMarker(psStream, ui32Marker);
@@ -624,5 +798,8 @@ IMG_VOID PDumpResumeKM(IMG_VOID)
atomic_dec(&gsPDumpSuspended);
}
-#endif
-#endif
+#endif /* #if defined (PDUMP) */
+#endif /* #if defined (SUPPORT_SGX) */
+/*****************************************************************************
+ End of file (PDUMP.C)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/private_data.h b/sgx/services4/srvkm/env/linux/private_data.h
index a460798..1b0f045 100644
--- a/sgx/services4/srvkm/env/linux/private_data.h
+++ b/sgx/services4/srvkm/env/linux/private_data.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linux private data structure
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __INCLUDED_PRIVATE_DATA_H_
#define __INCLUDED_PRIVATE_DATA_H_
@@ -32,12 +48,23 @@
#include <drm/drmP.h>
#endif
+/* This structure is required in the rare case that a process creates
+ * a connection to services, but before closing the file descriptor,
+ * does a fork(). This fork() will duplicate the file descriptor in the
+ * child process. If the parent process dies before the child, this can
+ * cause the PVRSRVRelease() method to be called in a different process
+ * context than the original PVRSRVOpen(). This is bad because we need
+ * to update the per-process data reference count and/or free the
+ * per-process data. So we must keep a record of which PID's per-process
+ * data to inspect during ->release().
+ */
+
typedef struct
{
-
+ /* PID that created this services connection */
IMG_UINT32 ui32OpenPID;
-
+ /* Global kernel MemInfo handle */
#if defined (SUPPORT_SID_INTERFACE)
IMG_SID hKernelMemInfo;
#else
@@ -45,22 +72,22 @@ typedef struct
#endif
#if defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT)
-
+ /* The private data is on a list in the per-process data structure */
struct list_head sDRMAuthListItem;
struct drm_file *psDRMFile;
#endif
#if defined(SUPPORT_MEMINFO_IDS)
-
+ /* Globally unique "stamp" for kernel MemInfo */
IMG_UINT64 ui64Stamp;
-#endif
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
-
+ /* Accounting for OSAllocMem */
IMG_HANDLE hBlockAlloc;
#if defined(SUPPORT_DRI_DRM_EXT)
- IMG_PVOID pPriv;
+ IMG_PVOID pPriv; /*private data for extending this struct*/
#endif
}
PVRSRV_FILE_PRIVATE_DATA;
@@ -97,5 +124,5 @@ static inline void set_private(struct file *file, PVRSRV_FILE_PRIVATE_DATA *priv
#endif
-#endif
+#endif /* __INCLUDED_PRIVATE_DATA_H_ */
diff --git a/sgx/services4/srvkm/env/linux/proc.c b/sgx/services4/srvkm/env/linux/proc.c
index 1df8aff..3b48c9e 100644
--- a/sgx/services4/srvkm/env/linux/proc.c
+++ b/sgx/services4/srvkm/env/linux/proc.c
@@ -1,28 +1,47 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Proc files implementation.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Functions for creating and reading proc filesystem entries.
+ Proc filesystem support must be built into the kernel for
+ these functions to be any use.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -52,6 +71,7 @@
#include "lists.h"
+// The proc entry for our /proc/pvr directory
static struct proc_dir_entry * dir;
static const IMG_CHAR PVRProcDirRoot[] = "pvr";
@@ -98,6 +118,28 @@ static void ProcSeqShowVersion(struct seq_file *sfile,void* el);
static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el);
static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off);
+/*!
+******************************************************************************
+
+ @Function : printAppend
+
+ @Description
+
+ Print into the supplied buffer at the specified offset remaining within
+ the specified total buffer size.
+
+ @Input size : the total size of the buffer
+
+ @Input off : the offset into the buffer to start printing
+
+ @Input format : the printf format string
+
+ @Input ... : format args
+
+ @Return : The number of chars now in the buffer (original value of 'off'
+ plus number of chars added); 'size' if full.
+
+*****************************************************************************/
off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
{
IMG_INT n;
@@ -109,10 +151,13 @@ off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * fo
n = vsnprintf (buffer+off, space, format, ap);
va_end (ap);
-
+ /* According to POSIX, n is greater than or equal to the size available if
+ * the print would have overflowed the buffer. Other platforms may
+ * return -1 if printing was truncated.
+ */
if (n >= (IMG_INT)space || n < 0)
{
-
+ /* Ensure final string is terminated */
buffer[size - 1] = 0;
return (off_t)(size - 1);
}
@@ -123,16 +168,50 @@ off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * fo
}
+/*!
+******************************************************************************
+
+ @Function : ProcSeq1ElementOff2Element
+
+ @Description
+
+ Heleper Offset -> Element function for /proc files with only one entry
+ without header.
+
+ @Input sfile : seq_file object related to /proc/ file
+
+ @Input off : the offset into the buffer (id of object)
+
+ @Return : Pointer to element to be shown.
+
+*****************************************************************************/
void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off)
{
PVR_UNREFERENCED_PARAMETER(sfile);
-
+ // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
if(!off)
return (void*)2;
return NULL;
}
+/*!
+******************************************************************************
+
+ @Function : ProcSeq1ElementHeaderOff2Element
+
+ @Description
+
+ Heleper Offset -> Element function for /proc files with only one entry
+ with header.
+
+ @Input sfile : seq_file object related to /proc/ file
+
+ @Input off : the offset into the buffer (id of object)
+
+ @Return : Pointer to element to be shown.
+
+*****************************************************************************/
void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
{
PVR_UNREFERENCED_PARAMETER(sfile);
@@ -142,7 +221,7 @@ void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
return PVR_PROC_SEQ_START_TOKEN;
}
-
+ // Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL
if(off == 1)
return (void*)2;
@@ -150,6 +229,22 @@ void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off)
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_open
+
+ @Description
+ File opening function passed to proc_dir_entry->proc_fops for /proc entries
+ created by CreateProcReadEntrySeq.
+
+ @Input inode : inode entry of opened /proc file
+
+ @Input file : file entry of opened /proc file
+
+ @Return : 0 if no errors
+
+*****************************************************************************/
static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
{
IMG_INT ret = seq_open(file, &pvr_proc_seq_operations);
@@ -157,11 +252,22 @@ static IMG_INT pvr_proc_open(struct inode *inode,struct file *file)
struct seq_file *seq = (struct seq_file*)file->private_data;
struct proc_dir_entry* pvr_proc_entry = PDE(inode);
-
+ /* Add pointer to handlers to seq_file structure */
seq->private = pvr_proc_entry->data;
return ret;
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_write
+
+ @Description
+ File writing function passed to proc_dir_entry->proc_fops for /proc files.
+ It's exacly the same function that is used as default one (->fs/proc/generic.c),
+ it calls proc_dir_entry->write_proc for writing procedure.
+
+*****************************************************************************/
static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
size_t count, loff_t *ppos)
{
@@ -178,6 +284,23 @@ static ssize_t pvr_proc_write(struct file *file, const char __user *buffer,
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_start
+
+ @Description
+ Seq_file start function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ This function ises off2element handler.
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input pos : offset within file (id of entry)
+
+ @Return : Pointer to element from we start enumeration (0 ends it)
+
+*****************************************************************************/
static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
@@ -186,6 +309,20 @@ static void *pvr_proc_seq_start (struct seq_file *proc_seq_file, loff_t *pos)
return handlers->off2element(proc_seq_file, *pos);
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_stop
+
+ @Description
+ Seq_file stop function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input v : current element pointer
+
+*****************************************************************************/
static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
@@ -195,6 +332,25 @@ static void pvr_proc_seq_stop (struct seq_file *proc_seq_file, void *v)
handlers->startstop(proc_seq_file, IMG_FALSE);
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_next
+
+ @Description
+ Seq_file next element function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ It uses supplied 'next' handler for fetching next element (or 0 if there is no one)
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input pos : offset within file (id of entry)
+
+ @Input v : current element pointer
+
+ @Return : next element pointer (or 0 if end)
+
+*****************************************************************************/
static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t *pos)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
@@ -204,6 +360,23 @@ static void *pvr_proc_seq_next (struct seq_file *proc_seq_file, void *v, loff_t
return handlers->off2element(proc_seq_file, *pos);
}
+/*!
+******************************************************************************
+
+ @Function : pvr_proc_seq_show
+
+ @Description
+ Seq_file show element function. Detailed description of seq_file workflow can
+ be found here: http://tldp.org/LDP/lkmpg/2.6/html/x861.html.
+ It call proper 'show' handler to show (dump) current element using seq_* functions
+
+ @Input proc_seq_file : sequence file entry
+
+ @Input v : current element pointer
+
+ @Return : 0 if everything is OK
+
+*****************************************************************************/
static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
{
PVR_PROC_SEQ_HANDLERS *handlers = (PVR_PROC_SEQ_HANDLERS*)proc_seq_file->private;
@@ -213,6 +386,38 @@ static int pvr_proc_seq_show (struct seq_file *proc_seq_file, void *v)
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntryInDirSeq
+
+ @Description
+
+ Create a file under the given directory. These dynamic files can be used at
+ runtime to get or set information about the device. Whis version uses seq_file
+ interface
+
+ @Input pdir : parent directory
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+
+*****************************************************************************/
static struct proc_dir_entry* CreateProcEntryInDirSeq(
struct proc_dir_entry *pdir,
const IMG_CHAR * name,
@@ -259,7 +464,7 @@ static struct proc_dir_entry* CreateProcEntryInDirSeq(
file->proc_fops = &pvr_proc_operations;
file->write_proc = whandler;
-
+ /* Pass the handlers */
file->data = kmalloc(sizeof(PVR_PROC_SEQ_HANDLERS), GFP_KERNEL);
if(file->data)
{
@@ -279,6 +484,35 @@ static struct proc_dir_entry* CreateProcEntryInDirSeq(
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcReadEntrySeq
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get information about the device. Creation WILL fail if proc support is
+ not compiled into the kernel. That said, the Linux kernel is not even happy
+ to build without /proc support these days. This version uses seq_file structure
+ for handling content generation.
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
struct proc_dir_entry* CreateProcReadEntrySeq (
const IMG_CHAR * name,
IMG_VOID* data,
@@ -297,6 +531,40 @@ struct proc_dir_entry* CreateProcReadEntrySeq (
NULL);
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntrySeq
+
+ @Description
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get information about the device. Creation WILL fail if proc support is
+ not compiled into the kernel. That said, the Linux kernel is not even happy
+ to build without /proc support these days. This version uses seq_file structure
+ for handling content generation and is fuller than CreateProcReadEntrySeq (it
+ supports write access);
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
struct proc_dir_entry* CreateProcEntrySeq (
const IMG_CHAR * name,
IMG_VOID* data,
@@ -321,6 +589,37 @@ struct proc_dir_entry* CreateProcEntrySeq (
+/*!
+******************************************************************************
+
+ @Function : CreatePerProcessProcEntrySeq
+
+ @Description
+
+ Create a file under /proc/pvr/<current process ID>. Apart from the
+ directory where the file is created, this works the same way as
+ CreateProcEntry. It's seq_file version.
+
+
+
+ @Input name : the name of the file to create
+
+ @Input data : aditional data that will be passed to handlers
+
+ @Input next_handler : the function to call to provide the next element. OPTIONAL, if not
+ supplied, then off2element function is used instead
+
+ @Input show_handler : the function to call to show element
+
+ @Input off2element_handler : the function to call when it is needed to translate offest to element
+
+ @Input startstop_handler : the function to call when output memory page starts or stops. OPTIONAL.
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return Ptr to proc entry , 0 for failure
+
+*****************************************************************************/
struct proc_dir_entry* CreatePerProcessProcEntrySeq (
const IMG_CHAR * name,
IMG_VOID* data,
@@ -379,6 +678,20 @@ struct proc_dir_entry* CreatePerProcessProcEntrySeq (
}
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntrySeq
+
+ @Description
+
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
{
if (dir)
@@ -393,6 +706,22 @@ IMG_VOID RemoveProcEntrySeq( struct proc_dir_entry* proc_entry )
}
}
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcEntry Seq
+
+ @Description
+
+ Remove a single node under the per process proc directory (created by *Seq function).
+
+ Remove a single node (created using *Seq function) under /proc/pvr.
+
+ @Input proc_entry : structure returned by Create function.
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
@@ -420,10 +749,46 @@ IMG_VOID RemovePerProcessProcEntrySeq(struct proc_dir_entry* proc_entry)
}
}
+/*!
+******************************************************************************
+
+ @Function : pvr_read_proc_vm
+
+ @Description
+
+ When the user accesses the proc filesystem entry for the device, we are
+ called here to create the content for the 'file'. We can print anything we
+ want here. If the info we want to return is too big for one page ('count'
+ chars), we return successive chunks on each call. For a number of ways of
+ achieving this, refer to proc_file_read() in linux/fs/proc/generic.c.
+
+ Here, as we are accessing lists of information, we output '1' in '*start' to
+ instruct proc to advance 'off' by 1 on each call. The number of chars placed
+ in the buffer is returned. Multiple calls are made here by the proc
+ filesystem until we set *eof. We can return zero without setting eof to
+ instruct proc to flush 'page' (causing it to be printed) if there is not
+ enough space left (eg for a complete line).
+
+ @Input page : where to write the output
+
+ @Input start : memory location into which should be written next offset
+ to read from.
+
+ @Input off : the offset into the /proc file being read
+
+ @Input count : the size of the buffer 'page'
+
+ @Input eof : memory location into which 1 should be written when at EOF
+
+ @Input data : data specific to this /proc file entry
+
+ @Return : length of string written to page
+
+*****************************************************************************/
static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
IMG_INT count, IMG_INT *eof, IMG_VOID *data)
{
-
+ /* PRQA S 0307 1 */ /* ignore warning about casting to different pointer type */
pvr_read_proc_t *pprn = (pvr_read_proc_t *)data;
off_t len = pprn (page, (size_t)count, off);
@@ -433,9 +798,9 @@ static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
len = 0;
*eof = 1;
}
- else if (!len)
+ else if (!len) /* not enough space in the buffer */
{
- *start = (IMG_CHAR *) 0;
+ *start = (IMG_CHAR *) 0; /* don't advance the offset */
}
else
{
@@ -446,6 +811,27 @@ static IMG_INT pvr_read_proc(IMG_CHAR *page, IMG_CHAR **start, off_t off,
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntryInDir
+
+ @Description
+
+ Create a file under the given directory. These dynamic files can be used at
+ runtime to get or set information about the device.
+
+ @Input pdir : parent directory
+
+ @Input name : the name of the file to create
+
+ @Input rhandler : the function to supply the content
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return success code : 0 or -errno.
+
+*****************************************************************************/
static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
{
struct proc_dir_entry * file;
@@ -492,12 +878,54 @@ static IMG_INT CreateProcEntryInDir(struct proc_dir_entry *pdir, const IMG_CHAR
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntry
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get or set information about the device.
+
+ This interface is fuller than CreateProcReadEntry, and supports write access;
+ it is really just a wrapper for the native linux functions.
+
+ @Input name : the name of the file to create under /proc/pvr
+
+ @Input rhandler : the function to supply the content
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return success code : 0 or -errno.
+
+*****************************************************************************/
IMG_INT CreateProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
{
return CreateProcEntryInDir(dir, name, rhandler, whandler, data);
}
+/*!
+******************************************************************************
+
+ @Function : CreatePerProcessProcEntry
+
+ @Description
+
+ Create a file under /proc/pvr/<current process ID>. Apart from the
+ directory where the file is created, this works the same way as
+ CreateProcEntry.
+
+ @Input name : the name of the file to create under the per process /proc directory
+
+ @Input rhandler : the function to supply the content
+
+ @Input whandler : the function to interpret writes from the user
+
+ @Return success code : 0 or -errno.
+
+*****************************************************************************/
IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, write_proc_t whandler, IMG_VOID *data)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
@@ -549,6 +977,25 @@ IMG_INT CreatePerProcessProcEntry(const IMG_CHAR * name, read_proc_t rhandler, w
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcReadEntry
+
+ @Description
+
+ Create a file under /proc/pvr. These dynamic files can be used at runtime
+ to get information about the device. Creation WILL fail if proc support is
+ not compiled into the kernel. That said, the Linux kernel is not even happy
+ to build without /proc support these days.
+
+ @Input name : the name of the file to create
+
+ @Input handler : the function to call to provide the content
+
+ @Return 0 for success, -errno for failure
+
+*****************************************************************************/
IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
{
struct proc_dir_entry * file;
@@ -560,7 +1007,7 @@ IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
return -ENOMEM;
}
-
+ /* PRQA S 0307 1 */ /* ignore warning about casting to different pointer type */
file = create_proc_read_entry (name, S_IFREG | S_IRUGO, dir, pvr_read_proc, (IMG_VOID *)handler);
if (file)
@@ -577,6 +1024,23 @@ IMG_INT CreateProcReadEntry(const IMG_CHAR * name, pvr_read_proc_t handler)
}
+/*!
+******************************************************************************
+
+ @Function : CreateProcEntries
+
+ @Description
+
+ Create a directory /proc/pvr and the necessary entries within it. These
+ dynamic files can be used at runtime to get information about the device.
+ Creation might fail if proc support is not compiled into the kernel or if
+ there is no memory
+
+ @Input none
+
+ @Return nothing
+
+*****************************************************************************/
IMG_INT CreateProcEntries(IMG_VOID)
{
dir = proc_mkdir (PVRProcDirRoot, NULL);
@@ -631,6 +1095,20 @@ IMG_INT CreateProcEntries(IMG_VOID)
}
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntry
+
+ @Description
+
+ Remove a single node under /proc/pvr.
+
+ @Input name : the name of the node to remove
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
{
if (dir)
@@ -641,6 +1119,20 @@ IMG_VOID RemoveProcEntry(const IMG_CHAR * name)
}
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcEntry
+
+ @Description
+
+ Remove a single node under the per process proc directory.
+
+ @Input name : the name of the node to remove
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
{
PVRSRV_ENV_PER_PROCESS_DATA *psPerProc;
@@ -666,6 +1158,20 @@ IMG_VOID RemovePerProcessProcEntry(const IMG_CHAR *name)
}
+/*!
+******************************************************************************
+
+ @Function : RemovePerProcessProcDir
+
+ @Description
+
+ Remove the per process directorty under /proc/pvr.
+
+ @Input psPerProc : environment specific per process data
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
{
if (psPerProc->psProcDir)
@@ -680,13 +1186,28 @@ IMG_VOID RemovePerProcessProcDir(PVRSRV_ENV_PER_PROCESS_DATA *psPerProc)
}
}
+/*!
+******************************************************************************
+
+ @Function : RemoveProcEntries
+
+ Description
+
+ Proc filesystem entry deletion - Remove all proc filesystem entries for
+ the driver.
+
+ @Input none
+
+ @Return nothing
+
+*****************************************************************************/
IMG_VOID RemoveProcEntries(IMG_VOID)
{
#ifdef DEBUG
RemoveProcEntrySeq( g_pProcDebugLevel );
#ifdef PVR_MANUAL_POWER_CONTROL
RemoveProcEntrySeq( g_pProcPowerLevel );
-#endif
+#endif /* PVR_MANUAL_POWER_CONTROL */
#endif
RemoveProcEntrySeq(g_pProcQueue);
@@ -703,6 +1224,14 @@ IMG_VOID RemoveProcEntries(IMG_VOID)
remove_proc_entry(PVRProcDirRoot, NULL);
}
+/*****************************************************************************
+ FUNCTION : ProcSeqShowVersion
+
+ PURPOSE : Print the content of version to /proc file
+
+ PARAMETERS : sfile - /proc seq_file
+ el - Element to print
+*****************************************************************************/
static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
{
SYS_DATA *psSysData;
@@ -726,6 +1255,24 @@ static void ProcSeqShowVersion(struct seq_file *sfile,void* el)
seq_printf( sfile, "System Version String: %s\n", pszSystemVersionString);
}
+/*!
+******************************************************************************
+
+ @Function procDumpSysNodes (plus deviceTypeToString and deviceClassToString)
+
+ @Description
+
+ Format the contents of /proc/pvr/nodes
+
+ @Input buf : where to place format contents data.
+
+ @Input size : the size of the buffer into which to place data
+
+ @Input off : how far into the file we are.
+
+ @Return amount of data placed in buffer, 0, or END_OF_FILE :
+
+******************************************************************************/
static const IMG_CHAR *deviceTypeToString(PVRSRV_DEVICE_TYPE deviceType)
{
switch (deviceType)
@@ -781,6 +1328,14 @@ static IMG_VOID* DecOffPsDev_AnyVaCb(PVRSRV_DEVICE_NODE *psNode, va_list va)
}
}
+/*****************************************************************************
+ FUNCTION : ProcSeqShowSysNodes
+
+ PURPOSE : Print the content of version to /proc file
+
+ PARAMETERS : sfile - /proc seq_file
+ el - Element to print
+*****************************************************************************/
static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
{
PVRSRV_DEVICE_NODE *psDevNode;
@@ -807,6 +1362,16 @@ static void ProcSeqShowSysNodes(struct seq_file *sfile,void* el)
psDevNode->hResManContext);
}
+/*****************************************************************************
+ FUNCTION : ProcSeqOff2ElementSysNodes
+
+ PURPOSE : Transale offset to element (/proc stuff)
+
+ PARAMETERS : sfile - /proc seq_file
+ off - the offset into the buffer
+
+ RETURNS : element to print
+*****************************************************************************/
static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
{
SYS_DATA *psSysData;
@@ -822,14 +1387,17 @@ static void* ProcSeqOff2ElementSysNodes(struct seq_file * sfile, loff_t off)
psSysData = SysAcquireDataNoCheck();
if (psSysData != IMG_NULL)
{
-
+ /* Find Dev Node */
psDevNode = (PVRSRV_DEVICE_NODE*)
List_PVRSRV_DEVICE_NODE_Any_va(psSysData->psDeviceNodeList,
DecOffPsDev_AnyVaCb,
&off);
}
-
+ /* Return anything that is not PVR_RPOC_SEQ_START_TOKEN and NULL */
return (void*)psDevNode;
}
+/*****************************************************************************
+ End of file (proc.c)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/env/linux/proc.h b/sgx/services4/srvkm/env/linux/proc.h
index 2066d71..67cded7 100644
--- a/sgx/services4/srvkm/env/linux/proc.h
+++ b/sgx/services4/srvkm/env/linux/proc.h
@@ -1,35 +1,53 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Proc interface definition.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Functions for creating and reading proc filesystem entries.
+ Refer to proc.c
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __SERVICES_PROC_H__
#define __SERVICES_PROC_H__
-#include <asm/system.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
+#include <asm/system.h> // va_list etc
+#include <linux/proc_fs.h> // read_proc_t etc
+#include <linux/seq_file.h> // seq_file
#define END_OF_FILE (off_t) -1
@@ -51,8 +69,10 @@ typedef struct _PVR_PROC_SEQ_HANDLERS_ {
} PVR_PROC_SEQ_HANDLERS;
+/** off2element function for elements with only ONE element (no header) */
void* ProcSeq1ElementOff2Element(struct seq_file *sfile, loff_t off);
+/** off2element function for elements with only ONE element (+ header) */
void* ProcSeq1ElementHeaderOff2Element(struct seq_file *sfile, loff_t off);
off_t printAppend(IMG_CHAR * buffer, size_t size, off_t off, const IMG_CHAR * format, ...)
diff --git a/sgx/services4/srvkm/env/linux/pvr_bridge_k.c b/sgx/services4/srvkm/env/linux/pvr_bridge_k.c
index 373b586..037b4c9 100644
--- a/sgx/services4/srvkm/env/linux/pvr_bridge_k.c
+++ b/sgx/services4/srvkm/env/linux/pvr_bridge_k.c
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PVR Bridge Module (kernel side)
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Receives calls from the user portion of services and
+ despatches them to functions in the kernel portion.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "img_defs.h"
#include "services.h"
@@ -36,6 +54,8 @@
#include "linkage.h"
#include "pvr_bridge_km.h"
#include "pvr_uaccess.h"
+#include "refcount.h"
+#include "buffer_manager.h"
#if defined(SUPPORT_DRI_DRM)
#include <drm/drmP.h>
@@ -45,10 +65,12 @@
#endif
#endif
+/* VGX: */
#if defined(SUPPORT_VGX)
#include "vgx_bridge.h"
#endif
+/* SGX: */
#if defined(SUPPORT_SGX)
#include "sgx_bridge.h"
#endif
@@ -69,7 +91,7 @@ extern PVRSRV_LINUX_MUTEX gPVRSRVLock;
#if defined(SUPPORT_MEMINFO_IDS)
static IMG_UINT64 ui64Stamp;
-#endif
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
PVRSRV_ERROR
LinuxBridgeInit(IMG_VOID)
@@ -103,6 +125,13 @@ LinuxBridgeDeInit(IMG_VOID)
#if defined(DEBUG_BRIDGE_KM)
+/*
+ * Lock MMap regions list (called on page start/stop while reading /proc/mmap)
+ *
+ * sfile : seq_file that handles /proc file
+ * start : TRUE if it's start, FALSE if it's stop
+ *
+ */
static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
{
if(start)
@@ -116,6 +145,16 @@ static void ProcSeqStartstopBridgeStats(struct seq_file *sfile,IMG_BOOL start)
}
+/*
+ * Convert offset (index from KVOffsetTable) to element
+ * (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element that will be dumped
+ *
+*/
static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
{
if(!off)
@@ -132,12 +171,28 @@ static void* ProcSeqOff2ElementBridgeStats(struct seq_file *sfile, loff_t off)
return (void*)&g_BridgeDispatchTable[off-1];
}
+/*
+ * Gets next MMap element to show. (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ * off : index into the KVOffsetTable from which to print
+ *
+ * returns void* : Pointer to element to show (0 ends iteration)
+*/
static void* ProcSeqNextBridgeStats(struct seq_file *sfile,void* el,loff_t off)
{
return ProcSeqOff2ElementBridgeStats(sfile,off);
}
+/*
+ * Show MMap element (called when reading /proc/mmap file)
+
+ * sfile : seq_file that handles /proc file
+ * el : actual element
+ *
+*/
static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
{
PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY *psEntry = ( PVRSRV_BRIDGE_DISPATCH_TABLE_ENTRY*)el;
@@ -172,7 +227,7 @@ static void ProcSeqShowBridgeStats(struct seq_file *sfile,void* el)
psEntry->ui32CopyToUserTotalBytes);
}
-#endif
+#endif /* DEBUG_BRIDGE_KM */
#if defined(SUPPORT_DRI_DRM)
@@ -211,7 +266,9 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
goto unlock_and_return;
}
-
+ /* FIXME - Currently the CopyFromUserWrapper which collects stats about
+ * how much data is shifted to/from userspace isn't available to us
+ * here. */
if(OSCopyFromUser(IMG_NULL,
psBridgePackageKM,
psBridgePackageUM,
@@ -249,7 +306,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
}
else
{
-
+ /* lookup per-process data for this process */
psPerProc = PVRSRVPerProcessData(ui32PID);
if(psPerProc == IMG_NULL)
{
@@ -328,7 +385,13 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
break;
}
-
+ /*
+ * The DRM file structure we are using for Services
+ * is not one that DRI authentication was done on.
+ * Look for an authenticated file structure for
+ * this process, making sure the DRM master is the
+ * same as ours.
+ */
psEnvPerProc = (PVRSRV_ENV_PER_PROCESS_DATA *)PVRSRVProcessPrivateData(psPerProc);
if (psEnvPerProc == IMG_NULL)
{
@@ -362,7 +425,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
default:
break;
}
-#endif
+#endif /* defined(SUPPORT_DRI_DRM) && defined(PVR_SECURE_DRM_AUTH_EXPORT) */
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
{
@@ -384,15 +447,40 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *psExportDeviceMemOUT =
(PVRSRV_BRIDGE_OUT_EXPORTDEVICEMEM *)psBridgePackageKM->pvParamOut;
PVRSRV_FILE_PRIVATE_DATA *psPrivateData = get_private(pFile);
+ IMG_HANDLE hMemInfo;
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo;
- if (pvr_get_user(psPrivateData->hKernelMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
+ if (pvr_get_user(hMemInfo, &psExportDeviceMemOUT->hMemInfo) != 0)
{
err = -EFAULT;
goto unlock_and_return;
}
+
+ /* Look up the meminfo we just exported */
+ if(PVRSRVLookupHandle(KERNEL_HANDLE_BASE,
+ (IMG_PVOID *)&psKernelMemInfo,
+ hMemInfo,
+ PVRSRV_HANDLE_TYPE_MEM_INFO) != PVRSRV_OK)
+ {
+ PVR_DPF((PVR_DBG_ERROR, "%s: Failed to look up export handle", __FUNCTION__));
+ err = -EFAULT;
+ goto unlock_and_return;
+ }
+
+ /* Bump the refcount; decremented on release of the fd */
+ PVRSRVKernelMemInfoIncRef(psKernelMemInfo);
+
+ /* Tell the XProc about the export if required */
+ if (psKernelMemInfo->sShareMemWorkaround.bInUse)
+ {
+ BM_XProcIndexAcquire(psKernelMemInfo->sShareMemWorkaround.ui32ShareIndex);
+ }
+
+ psPrivateData->hKernelMemInfo = hMemInfo;
#if defined(SUPPORT_MEMINFO_IDS)
psPrivateData->ui64Stamp = ++ui64Stamp;
+ psKernelMemInfo->ui64Stamp = psPrivateData->ui64Stamp;
if (pvr_put_user(psPrivateData->ui64Stamp, &psExportDeviceMemOUT->ui64Stamp) != 0)
{
err = -EFAULT;
@@ -404,6 +492,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
#if defined(SUPPORT_MEMINFO_IDS)
case PVRSRV_BRIDGE_MAP_DEV_MEMORY:
+ case PVRSRV_BRIDGE_MAP_DEV_MEMORY_2:
{
PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *psMapDeviceMemoryOUT =
(PVRSRV_BRIDGE_OUT_MAP_DEV_MEMORY *)psBridgePackageKM->pvParamOut;
@@ -427,7 +516,7 @@ PVRSRV_BridgeDispatchKM(struct file *pFile, unsigned int unref__ ioctlCmd, unsig
}
break;
}
-#endif
+#endif /* defined(SUPPORT_MEMINFO_IDS) */
default:
break;
diff --git a/sgx/services4/srvkm/env/linux/pvr_debug.c b/sgx/services4/srvkm/env/linux/pvr_debug.c
index 7690875..ad3e32b 100644
--- a/sgx/services4/srvkm/env/linux/pvr_debug.c
+++ b/sgx/services4/srvkm/env/linux/pvr_debug.c
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Debug Functionality
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides kernel side Debug Functionality
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <linux/version.h>
@@ -38,7 +55,7 @@
#include <linux/hardirq.h>
#include <linux/module.h>
#include <linux/spinlock.h>
-#include <linux/string.h>
+#include <linux/string.h> // strncpy, strlen
#include <stdarg.h>
#include "img_types.h"
#include "servicesext.h"
@@ -49,6 +66,10 @@
#include "linkage.h"
#include "pvr_uaccess.h"
+#if !defined(CONFIG_PREEMPT)
+#define PVR_DEBUG_ALWAYS_USE_SPINLOCK
+#endif
+
static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
const IMG_CHAR* pszFormat, va_list VArgs)
IMG_FORMAT_PRINTF(3, 0);
@@ -62,67 +83,96 @@ static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz,
const IMG_CHAR *pszFormat, ...)
IMG_FORMAT_PRINTF(3, 4);
+/* NOTE: Must NOT be static! Used in module.c.. */
IMG_UINT32 gPVRDebugLevel =
(DBGPRIV_FATAL | DBGPRIV_ERROR | DBGPRIV_WARNING);
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_DPF) || defined(PVRSRV_NEED_PVR_TRACE) */
#define PVR_MAX_MSG_LEN PVR_MAX_DEBUG_MESSAGE_LEN
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+/* Message buffer for non-IRQ messages */
static IMG_CHAR gszBufferNonIRQ[PVR_MAX_MSG_LEN + 1];
+#endif
+/* Message buffer for IRQ messages */
static IMG_CHAR gszBufferIRQ[PVR_MAX_MSG_LEN + 1];
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+/* The lock is used to control access to gszBufferNonIRQ */
static PVRSRV_LINUX_MUTEX gsDebugMutexNonIRQ;
+#endif
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
+/* The lock is used to control access to gszBufferIRQ */
+/* PRQA S 0671,0685 1 */ /* ignore warnings about C99 style initialisation */
static spinlock_t gsDebugLockIRQ = SPIN_LOCK_UNLOCKED;
#else
-static spinlock_t gsDebugLockIRQ = __SPIN_LOCK_UNLOCKED(gsDebugLockIRQ);
+static DEFINE_SPINLOCK(gsDebugLockIRQ);
#endif
-#if !defined (USE_SPIN_LOCK)
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
+#if !defined (USE_SPIN_LOCK) /* to keep QAC happy */
#define USE_SPIN_LOCK (in_interrupt() || !preemptible())
#endif
+#endif
static inline void GetBufferLock(unsigned long *pulLockFlags)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
if (USE_SPIN_LOCK)
+#endif
{
spin_lock_irqsave(&gsDebugLockIRQ, *pulLockFlags);
}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
LinuxLockMutex(&gsDebugMutexNonIRQ);
}
+#endif
}
static inline void ReleaseBufferLock(unsigned long ulLockFlags)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
if (USE_SPIN_LOCK)
+#endif
{
spin_unlock_irqrestore(&gsDebugLockIRQ, ulLockFlags);
}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
LinuxUnLockMutex(&gsDebugMutexNonIRQ);
}
+#endif
}
static inline void SelectBuffer(IMG_CHAR **ppszBuf, IMG_UINT32 *pui32BufSiz)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
if (USE_SPIN_LOCK)
+#endif
{
*ppszBuf = gszBufferIRQ;
*pui32BufSiz = sizeof(gszBufferIRQ);
}
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
else
{
*ppszBuf = gszBufferNonIRQ;
*pui32BufSiz = sizeof(gszBufferNonIRQ);
}
+#endif
}
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, pointed
+ * to by the var args list.
+ */
static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR* pszFormat, va_list VArgs)
{
IMG_UINT32 ui32Used;
@@ -136,15 +186,27 @@ static IMG_BOOL VBAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR
i32Len = vsnprintf(&pszBuf[ui32Used], ui32Space, pszFormat, VArgs);
pszBuf[ui32BufSiz - 1] = 0;
-
+ /* Return true if string was truncated */
return (i32Len < 0 || i32Len >= (IMG_INT32)ui32Space) ? IMG_TRUE : IMG_FALSE;
}
+/* Actually required for ReleasePrintf too */
+
IMG_VOID PVRDPFInit(IMG_VOID)
{
+#if !defined(PVR_DEBUG_ALWAYS_USE_SPINLOCK)
LinuxInitMutex(&gsDebugMutexNonIRQ);
+#endif
}
+/*!
+******************************************************************************
+ @Function PVRSRVReleasePrintf
+ @Description To output an important message to the user in release builds
+ @Input pszFormat - The message format string
+ @Input ... - Zero or more arguments for use by the format string
+ @Return None
+ ******************************************************************************/
IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
{
va_list vaArgs;
@@ -173,18 +235,16 @@ IMG_VOID PVRSRVReleasePrintf(const IMG_CHAR *pszFormat, ...)
}
-#if defined(PVRSRV_NEED_PVR_ASSERT)
-
-IMG_VOID PVRSRVDebugAssertFail(const IMG_CHAR* pszFile, IMG_UINT32 uLine)
-{
- PVRSRVDebugPrintf(DBGPRIV_FATAL, pszFile, uLine, "Debug assertion failed!");
- BUG();
-}
-
-#endif
-
#if defined(PVRSRV_NEED_PVR_TRACE)
+/*!
+******************************************************************************
+ @Function PVRTrace
+ @Description To output a debug message to the user
+ @Input pszFormat - The message format string
+ @Input ... - Zero or more arguments for use by the format string
+ @Return None
+ ******************************************************************************/
IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
{
va_list VArgs;
@@ -214,10 +274,15 @@ IMG_VOID PVRSRVTrace(const IMG_CHAR* pszFormat, ...)
va_end(VArgs);
}
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_TRACE) */
#if defined(PVRSRV_NEED_PVR_DPF)
+/*
+ * Append a string to a buffer using formatted conversion.
+ * The function takes a variable number of arguments, calling
+ * VBAppend to do the actual work.
+ */
static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR *pszFormat, ...)
{
va_list VArgs;
@@ -232,6 +297,17 @@ static IMG_BOOL BAppend(IMG_CHAR *pszBuf, IMG_UINT32 ui32BufSiz, const IMG_CHAR
return bTrunc;
}
+/*!
+******************************************************************************
+ @Function PVRSRVDebugPrintf
+ @Description To output a debug message to the user
+ @Input uDebugLevel - The current debug level
+ @Input pszFile - The source file generating the message
+ @Input uLine - The line of the source file
+ @Input pszFormat - The message format string
+ @Input ... - Zero or more arguments for use by the format string
+ @Return None
+ ******************************************************************************/
IMG_VOID PVRSRVDebugPrintf (
IMG_UINT32 ui32DebugLevel,
const IMG_CHAR* pszFullFileName,
@@ -260,7 +336,7 @@ IMG_VOID PVRSRVDebugPrintf (
GetBufferLock(&ulLockFlags);
-
+ /* Add in the level of warning */
if (bTrace == IMG_FALSE)
{
switch(ui32DebugLevel)
@@ -308,21 +384,22 @@ IMG_VOID PVRSRVDebugPrintf (
}
else
{
-
+ /* Traces don't need a location */
if (bTrace == IMG_FALSE)
{
#ifdef DEBUG_LOG_PATH_TRUNCATE
-
+ /* Buffer for rewriting filepath in log messages */
static IMG_CHAR szFileNameRewrite[PVR_MAX_FILEPATH_LEN];
IMG_CHAR* pszTruncIter;
IMG_CHAR* pszTruncBackInter;
-
+ /* Truncate path (DEBUG_LOG_PATH_TRUNCATE shoud be set to EURASIA env var)*/
if (strlen(pszFullFileName) > strlen(DEBUG_LOG_PATH_TRUNCATE)+1)
pszFileName = pszFullFileName + strlen(DEBUG_LOG_PATH_TRUNCATE)+1;
-
+ /* Try to find '/../' entries and remove it together with
+ previous entry. Repeat unit all removed */
strncpy(szFileNameRewrite, pszFileName,PVR_MAX_FILEPATH_LEN);
if(strlen(szFileNameRewrite) == PVR_MAX_FILEPATH_LEN-1) {
@@ -334,7 +411,7 @@ IMG_VOID PVRSRVDebugPrintf (
while(*pszTruncIter++ != 0)
{
IMG_CHAR* pszNextStartPoint;
-
+ /* Find '/../' pattern */
if(
!( ( *pszTruncIter == '/' && (pszTruncIter-4 >= szFileNameRewrite) ) &&
( *(pszTruncIter-1) == '.') &&
@@ -342,7 +419,7 @@ IMG_VOID PVRSRVDebugPrintf (
( *(pszTruncIter-3) == '/') )
) continue;
-
+ /* Find previous '/' */
pszTruncBackInter = pszTruncIter - 3;
while(*(--pszTruncBackInter) != '/')
{
@@ -350,19 +427,19 @@ IMG_VOID PVRSRVDebugPrintf (
}
pszNextStartPoint = pszTruncBackInter;
-
+ /* Remove found region */
while(*pszTruncIter != 0)
{
*pszTruncBackInter++ = *pszTruncIter++;
}
*pszTruncBackInter = 0;
-
+ /* Start again */
pszTruncIter = pszNextStartPoint;
}
pszFileName = szFileNameRewrite;
-
+ /* Remove first '/' if exist (it's always relative path */
if(*pszFileName == '/') pszFileName++;
#endif
@@ -373,7 +450,7 @@ IMG_VOID PVRSRVDebugPrintf (
{
pszFileName = pszLeafName;
}
-#endif
+#endif /* __sh__ */
if (BAppend(pszBuf, ui32BufSiz, " [%u, %s]", ui32Line, pszFileName))
{
@@ -396,16 +473,16 @@ IMG_VOID PVRSRVDebugPrintf (
}
}
-#endif
+#endif /* PVRSRV_NEED_PVR_DPF */
#if defined(DEBUG)
IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT32 count, IMG_VOID *data)
{
-#define _PROC_SET_BUFFER_SZ 2
+#define _PROC_SET_BUFFER_SZ 6
IMG_CHAR data_buffer[_PROC_SET_BUFFER_SZ];
- if (count != _PROC_SET_BUFFER_SZ)
+ if (count > _PROC_SET_BUFFER_SZ)
{
return -EINVAL;
}
@@ -415,7 +492,9 @@ IMG_INT PVRDebugProcSetLevel(struct file *file, const IMG_CHAR *buffer, IMG_UINT
return -EINVAL;
if (data_buffer[count - 1] != '\n')
return -EINVAL;
- gPVRDebugLevel = data_buffer[0] - '0';
+ if (sscanf(data_buffer, "%i", &gPVRDebugLevel) == 0)
+ return -EINVAL;
+ gPVRDebugLevel &= (1 << DBGPRIV_DBGLEVEL_COUNT) - 1;
}
return (count);
}
@@ -425,4 +504,4 @@ void ProcSeqShowDebugLevel(struct seq_file *sfile,void* el)
seq_printf(sfile, "%u\n", gPVRDebugLevel);
}
-#endif
+#endif /* defined(DEBUG) */
diff --git a/sgx/services4/srvkm/env/linux/pvr_drm.c b/sgx/services4/srvkm/env/linux/pvr_drm.c
index 620c158..c955bcf 100644
--- a/sgx/services4/srvkm/env/linux/pvr_drm.c
+++ b/sgx/services4/srvkm/env/linux/pvr_drm.c
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title PowerVR drm driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description linux module setup
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if defined(SUPPORT_DRI_DRM)
#include <linux/version.h>
@@ -44,8 +60,9 @@
#include <drm/drmP.h>
#include <drm/drm.h>
-#ifdef SUPPORT_DRI_DRM_EXTERNAL
+#if defined(SUPPORT_DRI_DRM_EXTERNAL)
# include <linux/omap_drm.h>
+# include <linux/omap_drv.h>
#endif
#include "img_defs.h"
@@ -107,20 +124,20 @@ static struct platform_device_id asPlatIdList[] = {
{}
};
#endif
-#else
+#else /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
static struct pci_device_id asPciIdList[] = {
#if defined(PVR_DRI_DRM_NOT_PCI)
{1, 1, 1, 1, 0, 0, 0},
-#else
+#else /* defined(PVR_DRI_DRM_NOT_PCI) */
{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
#if defined(SYS_SGX_DEV1_DEVICE_ID)
{SYS_SGX_DEV_VENDOR_ID, SYS_SGX_DEV1_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
-#endif
-#endif
+#endif /* defined(SYS_SGX_DEV1_DEVICE_ID) */
+#endif /* defined(PVR_DRI_DRM_NOT_PCI) */
{0}
};
-#endif
-#endif
+#endif /* defined(PVR_DRI_DRM_PLATFORM_DEV) */
+#endif /* !defined(SUPPORT_DRI_DRM_EXT) */
DRI_DRM_STATIC int
PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
@@ -145,7 +162,7 @@ PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags)
goto exit;
}
#endif
-
+ /* Module initialisation */
iRes = PVRCore_Init();
if (iRes != 0)
{
@@ -268,7 +285,10 @@ PVRSRVDrmRelease(struct inode *inode, struct file *filp)
if (ret != 0)
{
-
+ /*
+ * An error means drm_release didn't call drm_lastclose,
+ * but it will have freed file_priv.
+ */
PVR_DPF((PVR_DBG_ERROR, "%s : drm_release failed: %d",
__FUNCTION__, ret));
}
@@ -352,13 +372,6 @@ PVRDRM_Display_ioctl(struct drm_device *dev, void *arg, struct drm_file *pFile)
#endif
#if !defined(SUPPORT_DRI_DRM_EXT)
-
-#if defined(DRM_IOCTL_DEF)
-#define PVR_DRM_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF(DRM_##ioctl, _func, _flags)
-#else
-#define PVR_DRM_IOCTL_DEF(ioctl, _func, _flags) DRM_IOCTL_DEF_DRV(ioctl, _func, _flags)
-#endif
-
struct drm_ioctl_desc sPVRDrmIoctls[] = {
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,35))
DRM_IOCTL_DEF(PVR_DRM_SRVKM_IOCTL, PVRSRV_BridgeDispatchKM, PVR_DRM_UNLOCKED),
@@ -403,7 +416,7 @@ static struct omap_drm_plugin plugin = {
.num_ioctls = ARRAY_SIZE(sPVRDrmIoctls),
.ioctl_base = 0, /* initialized when plugin is registered */
};
-#else
+#else /* defined(SUPPORT_DRI_DRM_EXTERNAL) */
static struct drm_driver sPVRDrmDriver =
{
#if defined(PVR_DRI_DRM_PLATFORM_DEV)
@@ -419,10 +432,8 @@ static struct drm_driver sPVRDrmDriver =
.suspend = PVRSRVDriverSuspend,
.resume = PVRSRVDriverResume,
#endif
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,37))
.get_map_ofs = drm_core_get_map_ofs,
.get_reg_ofs = drm_core_get_reg_ofs,
-#endif
.ioctls = sPVRDrmIoctls,
.fops =
{
@@ -482,7 +493,7 @@ PVRSRVDrmRemove(struct platform_device *pDevice)
return 0;
}
-#endif
+#endif
static int __init PVRSRVDrmInit(void)
{
@@ -491,7 +502,7 @@ static int __init PVRSRVDrmInit(void)
#if !defined(SUPPORT_DRI_DRM_EXTERNAL)
sPVRDrmDriver.num_ioctls = pvr_max_ioctl;
#endif
-
+
PVRDPFInit();
#if defined(PVR_DRI_DRM_NOT_PCI)
@@ -533,9 +544,14 @@ static void __exit PVRSRVDrmExit(void)
#endif
}
+/*
+ * These macro calls define the initialisation and removal functions of the
+ * driver. Although they are prefixed `module_', they apply when compiling
+ * statically as well; in both cases they define the function the kernel will
+ * run to start/stop the driver.
+*/
module_init(PVRSRVDrmInit);
module_exit(PVRSRVDrmExit);
-#endif
-#endif
-
+#endif
+#endif
diff --git a/sgx/services4/srvkm/env/linux/pvr_drm.h b/sgx/services4/srvkm/env/linux/pvr_drm.h
index 9d79602..5418c6d 100644
--- a/sgx/services4/srvkm/env/linux/pvr_drm.h
+++ b/sgx/services4/srvkm/env/linux/pvr_drm.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title PowerVR drm driver
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description drm module
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if !defined(__PVR_DRM_H__)
#define __PVR_DRM_H__
@@ -57,6 +73,7 @@ int PVRSRV_BridgeDispatchKM(struct drm_device *dev, void *arg, struct drm_file *
#if defined(SUPPORT_DRI_DRM_EXT)
#define DRI_DRM_STATIC
+/*Exported functions to common drm layer*/
int PVRSRVDrmLoad(struct drm_device *dev, unsigned long flags);
int PVRSRVDrmUnload(struct drm_device *dev);
int PVRSRVDrmOpen(struct drm_device *dev, struct drm_file *file);
@@ -70,7 +87,7 @@ int PVRDRMUnprivCmd(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFil
int PVRDRM_Dummy_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFile);
#else
#define DRI_DRM_STATIC static
-#endif
+#endif /* defined(SUPPORT_DRI_DRM_EXT) */
#if defined(DISPLAY_CONTROLLER)
extern int PVR_DRM_MAKENAME(DISPLAY_CONTROLLER, _Init)(struct drm_device *);
@@ -102,6 +119,7 @@ IMG_INT dbgdrv_ioctl(struct drm_device *dev, IMG_VOID *arg, struct drm_file *pFi
#define DRM_IOCTL_PVR_UNPRIV DRM_IO(DRM_COMMAND_BASE + DRM_PVR_UNPRIV)
#define DRM_IOCTL_PVR_DBGDRV DRM_IO(DRM_COMMAND_BASE + DRM_PVR_DBGDRV)
#endif
+
#endif
#endif
diff --git a/sgx/services4/srvkm/env/linux/pvr_uaccess.h b/sgx/services4/srvkm/env/linux/pvr_uaccess.h
index 6e7f1d3..31c218b 100644
--- a/sgx/services4/srvkm/env/linux/pvr_uaccess.h
+++ b/sgx/services4/srvkm/env/linux/pvr_uaccess.h
@@ -1,29 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Utility functions for user space access
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __PVR_UACCESS_H__
#define __PVR_UACCESS_H__
@@ -53,7 +68,10 @@ static inline unsigned long pvr_copy_to_user(void __user *pvTo, const void *pvFr
static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pvFrom, unsigned long ulBytes)
{
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,33))
-
+ /*
+ * The compile time correctness checking introduced for copy_from_user in
+ * Linux 2.6.33 isn't fully comaptible with our usage of the function.
+ */
if (access_ok(VERIFY_READ, pvFrom, ulBytes))
{
return __copy_from_user(pvTo, pvFrom, ulBytes);
@@ -67,5 +85,5 @@ static inline unsigned long pvr_copy_from_user(void *pvTo, const void __user *pv
#define pvr_put_user put_user
#define pvr_get_user get_user
-#endif
+#endif /* __PVR_UACCESS_H__ */
diff --git a/sgx/services4/srvkm/hwdefs/ocpdefs.h b/sgx/services4/srvkm/hwdefs/ocpdefs.h
index 3bbab7b..cc4d54e 100644
--- a/sgx/services4/srvkm/hwdefs/ocpdefs.h
+++ b/sgx/services4/srvkm/hwdefs/ocpdefs.h
@@ -1,37 +1,55 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OCP HW definitions.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _OCPDEFS_H_
#define _OCPDEFS_H_
+/* Register EUR_CR_OCP_REVISION */
#define EUR_CR_OCP_REVISION 0xFE00
#define EUR_CR_OCP_REVISION_REV_MASK 0xFFFFFFFFUL
#define EUR_CR_OCP_REVISION_REV_SHIFT 0
#define EUR_CR_OCP_REVISION_REV_SIGNED 0
+/* Register EUR_CR_OCP_HWINFO */
#define EUR_CR_OCP_HWINFO 0xFE04
#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_MASK 0x00000003UL
#define EUR_CR_OCP_HWINFO_SYS_BUS_WIDTH_SHIFT 0
@@ -41,6 +59,7 @@
#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SHIFT 2
#define EUR_CR_OCP_HWINFO_MEM_BUS_WIDTH_SIGNED 0
+/* Register EUR_CR_OCP_SYSCONFIG */
#define EUR_CR_OCP_SYSCONFIG 0xFE10
#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_MASK 0x0000000CUL
#define EUR_CR_OCP_SYSCONFIG_IDLE_MODE_SHIFT 2
@@ -50,66 +69,79 @@
#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SHIFT 4
#define EUR_CR_OCP_SYSCONFIG_STANDBY_MODE_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_0 */
#define EUR_CR_OCP_IRQSTATUS_RAW_0 0xFE24
#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_RAW_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_1 */
#define EUR_CR_OCP_IRQSTATUS_RAW_1 0xFE28
#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_RAW_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_RAW_2 */
#define EUR_CR_OCP_IRQSTATUS_RAW_2 0xFE2C
#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_RAW_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_0 */
#define EUR_CR_OCP_IRQSTATUS_0 0xFE30
#define EUR_CR_OCP_IRQSTATUS_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_1 */
#define EUR_CR_OCP_IRQSTATUS_1 0xFE34
#define EUR_CR_OCP_IRQSTATUS_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQSTATUS_2 */
#define EUR_CR_OCP_IRQSTATUS_2 0xFE38
#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQSTATUS_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_SET_0 */
#define EUR_CR_OCP_IRQENABLE_SET_0 0xFE3C
#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_SET_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_SET_1 */
#define EUR_CR_OCP_IRQENABLE_SET_1 0xFE40
#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_SET_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_SET_2 */
#define EUR_CR_OCP_IRQENABLE_SET_2 0xFE44
#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_SET_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_CLR_0 */
#define EUR_CR_OCP_IRQENABLE_CLR_0 0xFE48
#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_CLR_0_INIT_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_CLR_1 */
#define EUR_CR_OCP_IRQENABLE_CLR_1 0xFE4C
#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_CLR_1_TARGET_SIGNED 0
+/* Register EUR_CR_OCP_IRQENABLE_CLR_2 */
#define EUR_CR_OCP_IRQENABLE_CLR_2 0xFE50
#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_MASK 0x00000001UL
#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SHIFT 0
#define EUR_CR_OCP_IRQENABLE_CLR_2_SGXCORE_SIGNED 0
+/* Register EUR_CR_OCP_PAGE_CONFIG */
#define EUR_CR_OCP_PAGE_CONFIG 0xFF00
#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_MASK 0x00000001UL
#define EUR_CR_OCP_PAGE_CONFIG_MEM_PAGE_SIZE_SHIFT 0
@@ -123,6 +155,7 @@
#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SHIFT 3
#define EUR_CR_OCP_PAGE_CONFIG_SIZE_SIGNED 0
+/* Register EUR_CR_OCP_INTERRUPT_EVENT */
#define EUR_CR_OCP_INTERRUPT_EVENT 0xFF04
#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_MASK 0x00000001UL
#define EUR_CR_OCP_INTERRUPT_EVENT_INIT_RESP_UNEXPECTED_SHIFT 0
@@ -160,6 +193,7 @@
#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SHIFT 10
#define EUR_CR_OCP_INTERRUPT_EVENT_TARGET_INVALID_OCP_CMD_SIGNED 0
+/* Register EUR_CR_OCP_DEBUG_CONFIG */
#define EUR_CR_OCP_DEBUG_CONFIG 0xFF08
#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_MASK 0x00000003UL
#define EUR_CR_OCP_DEBUG_CONFIG_FORCE_TARGET_IDLE_SHIFT 0
@@ -181,6 +215,7 @@
#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SHIFT 31
#define EUR_CR_OCP_DEBUG_CONFIG_THALIA_INT_BYPASS_SIGNED 0
+/* Register EUR_CR_OCP_DEBUG_STATUS */
#define EUR_CR_OCP_DEBUG_STATUS 0xFF0C
#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_MASK 0x00000003UL
#define EUR_CR_OCP_DEBUG_STATUS_TARGET_MCONNECT_SHIFT 0
@@ -267,5 +302,8 @@
#define EUR_CR_OCP_DEBUG_STATUS_CMD_DEBUG_STATE_SIGNED 0
-#endif
+#endif /* _OCPDEFS_H_ */
+/*****************************************************************************
+ End of file (ocpdefs.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/hwdefs/sgx530defs.h b/sgx/services4/srvkm/hwdefs/sgx530defs.h
index 810cb81..d4ec16f 100644
--- a/sgx/services4/srvkm/hwdefs/sgx530defs.h
+++ b/sgx/services4/srvkm/hwdefs/sgx530defs.h
@@ -1,32 +1,49 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGX530.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _SGX530DEFS_KM_H_
#define _SGX530DEFS_KM_H_
+/* Register EUR_CR_CLKGATECTL */
#define EUR_CR_CLKGATECTL 0x0000
#define EUR_CR_CLKGATECTL_2D_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL_2D_CLKG_SHIFT 0
@@ -42,6 +59,7 @@
#define EUR_CR_CLKGATECTL_USE_CLKG_SHIFT 20
#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_MASK 0x01000000U
#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
+/* Register EUR_CR_CLKGATESTATUS */
#define EUR_CR_CLKGATESTATUS 0x0004
#define EUR_CR_CLKGATESTATUS_2D_CLKS_MASK 0x00000001U
#define EUR_CR_CLKGATESTATUS_2D_CLKS_SHIFT 0
@@ -55,6 +73,7 @@
#define EUR_CR_CLKGATESTATUS_DPM_CLKS_SHIFT 16
#define EUR_CR_CLKGATESTATUS_USE_CLKS_MASK 0x00100000U
#define EUR_CR_CLKGATESTATUS_USE_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
#define EUR_CR_CLKGATECTLOVR 0x0008
#define EUR_CR_CLKGATECTLOVR_2D_CLKO_MASK 0x00000003U
#define EUR_CR_CLKGATECTLOVR_2D_CLKO_SHIFT 0
@@ -68,11 +87,13 @@
#define EUR_CR_CLKGATECTLOVR_DPM_CLKO_SHIFT 16
#define EUR_CR_CLKGATECTLOVR_USE_CLKO_MASK 0x00300000U
#define EUR_CR_CLKGATECTLOVR_USE_CLKO_SHIFT 20
+/* Register EUR_CR_CORE_ID */
#define EUR_CR_CORE_ID 0x0010
#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_CORE_ID_ID_SHIFT 16
+/* Register EUR_CR_CORE_REVISION */
#define EUR_CR_CORE_REVISION 0x0014
#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
@@ -82,12 +103,15 @@
#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
#define EUR_CR_DESIGNER_REV_FIELD1 0x0018
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
#define EUR_CR_DESIGNER_REV_FIELD2 0x001C
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
#define EUR_CR_SOFT_RESET 0x0080
#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
@@ -103,6 +127,7 @@
#define EUR_CR_SOFT_RESET_ISP_RESET_SHIFT 5
#define EUR_CR_SOFT_RESET_TSP_RESET_MASK 0x00000040U
#define EUR_CR_SOFT_RESET_TSP_RESET_SHIFT 6
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
@@ -114,6 +139,7 @@
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
@@ -125,6 +151,7 @@
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
#define EUR_CR_EVENT_STATUS2 0x0118
#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
@@ -136,6 +163,7 @@
#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
#define EUR_CR_EVENT_STATUS 0x012CU
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
@@ -199,6 +227,7 @@
#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
#define EUR_CR_EVENT_HOST_ENABLE 0x0130
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
@@ -262,6 +291,7 @@
#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
#define EUR_CR_EVENT_HOST_CLEAR 0x0134
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
@@ -325,38 +355,49 @@
#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_PDS_EXEC_BASE */
#define EUR_CR_PDS_EXEC_BASE 0x0AB8
#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_EVENT_KICKER */
#define EUR_CR_EVENT_KICKER 0x0AC4
#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+/* Register EUR_CR_EVENT_KICK */
#define EUR_CR_EVENT_KICK 0x0AC8
#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+/* Register EUR_CR_EVENT_TIMER */
#define EUR_CR_EVENT_TIMER 0x0ACC
#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+/* Register EUR_CR_PDS_INV0 */
#define EUR_CR_PDS_INV0 0x0AD0
#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV1 */
#define EUR_CR_PDS_INV1 0x0AD4
#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV2 */
#define EUR_CR_PDS_INV2 0x0AD8
#define EUR_CR_PDS_INV2_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV2_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV3 */
#define EUR_CR_PDS_INV3 0x0ADC
#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV_CSC */
#define EUR_CR_PDS_INV_CSC 0x0AE0
#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+/* Register EUR_CR_PDS_PC_BASE */
#define EUR_CR_PDS_PC_BASE 0x0B2C
#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x3FFFFFFFU
#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+/* Register EUR_CR_BIF_CTRL */
#define EUR_CR_BIF_CTRL 0x0C00
#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
@@ -384,6 +425,7 @@
#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
#define EUR_CR_BIF_INT_STAT 0x0C04
#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
@@ -391,32 +433,41 @@
#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
#define EUR_CR_BIF_FAULT 0x0C08
#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TWOD_REQ_BASE */
#define EUR_CR_BIF_TWOD_REQ_BASE 0x0C88
#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_TWOD_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_TA_REQ_BASE */
#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_2D_BLIT_STATUS */
#define EUR_CR_2D_BLIT_STATUS 0x0E04
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
@@ -426,6 +477,7 @@
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
@@ -433,11 +485,14 @@
#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
#define EUR_CR_MNE_CR_CTRL 0x0D00
@@ -484,5 +539,5 @@
#define EUR_CR_MNE_CR_EVENT_CLEAR_INVAL_SHIFT 0
#define EUR_CR_MNE_CR_CTRL_INVAL 0x0D20
-#endif
+#endif /* _SGX530DEFS_KM_H_ */
diff --git a/sgx/services4/srvkm/hwdefs/sgx540defs.h b/sgx/services4/srvkm/hwdefs/sgx540defs.h
index c09aa26..25f9ec1 100644
--- a/sgx/services4/srvkm/hwdefs/sgx540defs.h
+++ b/sgx/services4/srvkm/hwdefs/sgx540defs.h
@@ -1,32 +1,49 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGX540.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _SGX540DEFS_KM_H_
#define _SGX540DEFS_KM_H_
+/* Register EUR_CR_CLKGATECTL */
#define EUR_CR_CLKGATECTL 0x0000
#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
@@ -52,6 +69,7 @@
#define EUR_CR_CLKGATECTL_AUTO_MAN_REG_SHIFT 24
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
+/* Register EUR_CR_CLKGATECTL2 */
#define EUR_CR_CLKGATECTL2 0x0004
#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
@@ -75,6 +93,7 @@
#define EUR_CR_CLKGATECTL2_TEX1_CLKG_SHIFT 18
#define EUR_CR_CLKGATECTL2_MADD1_CLKG_MASK 0x00300000U
#define EUR_CR_CLKGATECTL2_MADD1_CLKG_SHIFT 20
+/* Register EUR_CR_CLKGATESTATUS */
#define EUR_CR_CLKGATESTATUS 0x0008
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
@@ -118,6 +137,7 @@
#define EUR_CR_CLKGATESTATUS_IDXFIFO_CLKS_SHIFT 19
#define EUR_CR_CLKGATESTATUS_TA_CLKS_MASK 0x00100000U
#define EUR_CR_CLKGATESTATUS_TA_CLKS_SHIFT 20
+/* Register EUR_CR_CLKGATECTLOVR */
#define EUR_CR_CLKGATECTLOVR 0x000C
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
@@ -139,14 +159,17 @@
#define EUR_CR_CLKGATECTLOVR_IDXFIFO_CLKO_SHIFT 16
#define EUR_CR_CLKGATECTLOVR_TA_CLKO_MASK 0x000C0000U
#define EUR_CR_CLKGATECTLOVR_TA_CLKO_SHIFT 18
+/* Register EUR_CR_POWER */
#define EUR_CR_POWER 0x001C
#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001U
#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
+/* Register EUR_CR_CORE_ID */
#define EUR_CR_CORE_ID 0x0020
#define EUR_CR_CORE_ID_CONFIG_MASK 0x0000FFFFU
#define EUR_CR_CORE_ID_CONFIG_SHIFT 0
#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_CORE_ID_ID_SHIFT 16
+/* Register EUR_CR_CORE_REVISION */
#define EUR_CR_CORE_REVISION 0x0024
#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
@@ -156,12 +179,15 @@
#define EUR_CR_CORE_REVISION_MAJOR_SHIFT 16
#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
+/* Register EUR_CR_SOFT_RESET */
#define EUR_CR_SOFT_RESET 0x0080
#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
@@ -199,6 +225,7 @@
#define EUR_CR_SOFT_RESET_IDXFIFO_RESET_SHIFT 16
#define EUR_CR_SOFT_RESET_TA_RESET_MASK 0x00020000U
#define EUR_CR_SOFT_RESET_TA_RESET_SHIFT 17
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_ENABLE2_TRIG_TA_SHIFT 4
@@ -210,6 +237,7 @@
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_HOST_CLEAR2_TRIG_TA_SHIFT 4
@@ -221,6 +249,7 @@
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS2 */
#define EUR_CR_EVENT_STATUS2 0x0118
#define EUR_CR_EVENT_STATUS2_TRIG_TA_MASK 0x00000010U
#define EUR_CR_EVENT_STATUS2_TRIG_TA_SHIFT 4
@@ -232,6 +261,7 @@
#define EUR_CR_EVENT_STATUS2_DPM_3D_FREE_LOAD_SHIFT 1
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
+/* Register EUR_CR_EVENT_STATUS */
#define EUR_CR_EVENT_STATUS 0x012CU
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
@@ -295,6 +325,7 @@
#define EUR_CR_EVENT_STATUS_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
#define EUR_CR_EVENT_HOST_ENABLE 0x0130
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
@@ -358,6 +389,7 @@
#define EUR_CR_EVENT_HOST_ENABLE_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
#define EUR_CR_EVENT_HOST_CLEAR 0x0134
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
@@ -421,47 +453,61 @@
#define EUR_CR_EVENT_HOST_CLEAR_DPM_OUT_OF_MEMORY_MT_SHIFT 1
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
+/* Register EUR_CR_TIMER */
#define EUR_CR_TIMER 0x0144
#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
#define EUR_CR_TIMER_VALUE_SHIFT 0
+/* Register EUR_CR_EVENT_KICK1 */
#define EUR_CR_EVENT_KICK1 0x0AB0
#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
+/* Register EUR_CR_PDS_EXEC_BASE */
#define EUR_CR_PDS_EXEC_BASE 0x0AB8
#define EUR_CR_PDS_EXEC_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_PDS_EXEC_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_EVENT_KICK2 */
#define EUR_CR_EVENT_KICK2 0x0AC0
#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
+/* Register EUR_CR_EVENT_KICKER */
#define EUR_CR_EVENT_KICKER 0x0AC4
#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0x0FFFFFF0U
#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
+/* Register EUR_CR_EVENT_KICK */
#define EUR_CR_EVENT_KICK 0x0AC8
#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
+/* Register EUR_CR_EVENT_TIMER */
#define EUR_CR_EVENT_TIMER 0x0ACC
#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
+/* Register EUR_CR_PDS_INV0 */
#define EUR_CR_PDS_INV0 0x0AD0
#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV0_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV1 */
#define EUR_CR_PDS_INV1 0x0AD4
#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV1_DSC_SHIFT 0
+/* Register EUR_CR_EVENT_KICK3 */
#define EUR_CR_EVENT_KICK3 0x0AD8
#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
+/* Register EUR_CR_PDS_INV3 */
#define EUR_CR_PDS_INV3 0x0ADC
#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV3_DSC_SHIFT 0
+/* Register EUR_CR_PDS_INV_CSC */
#define EUR_CR_PDS_INV_CSC 0x0AE0
#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
+/* Register EUR_CR_PDS_PC_BASE */
#define EUR_CR_PDS_PC_BASE 0x0B2C
#define EUR_CR_PDS_PC_BASE_ADDRESS_MASK 0x00FFFFFFU
#define EUR_CR_PDS_PC_BASE_ADDRESS_SHIFT 0
+/* Register EUR_CR_BIF_CTRL */
#define EUR_CR_BIF_CTRL 0x0C00
#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
@@ -487,6 +533,7 @@
#define EUR_CR_BIF_CTRL_MMU_BYPASS_ISP_SHIFT 14
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_MASK 0x00008000U
#define EUR_CR_BIF_CTRL_MMU_BYPASS_USE_SHIFT 15
+/* Register EUR_CR_BIF_INT_STAT */
#define EUR_CR_BIF_INT_STAT 0x0C04
#define EUR_CR_BIF_INT_STAT_FAULT_MASK 0x00003FFFU
#define EUR_CR_BIF_INT_STAT_FAULT_SHIFT 0
@@ -494,31 +541,39 @@
#define EUR_CR_BIF_INT_STAT_PF_N_RW_SHIFT 14
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00008000U
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 15
+/* Register EUR_CR_BIF_FAULT */
#define EUR_CR_BIF_FAULT 0x0C08
#define EUR_CR_BIF_FAULT_SB_MASK 0x000001F0U
#define EUR_CR_BIF_FAULT_SB_SHIFT 4
#define EUR_CR_BIF_FAULT_ADDR_MASK 0x0FFFF000U
#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
+/* Register EUR_CR_BIF_TA_REQ_BASE */
#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0x0FF00000U
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
+/* Register EUR_CR_2D_BLIT_STATUS */
#define EUR_CR_2D_BLIT_STATUS 0x0E04
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
@@ -528,6 +583,7 @@
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_DIV_SHIFT 4
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
@@ -535,13 +591,16 @@
#define EUR_CR_2D_VIRTUAL_FIFO_1_MAX_ACC_SHIFT 12
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x00FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
#define EUR_CR_USE_CODE_BASE_DM_MASK 0x03000000U
#define EUR_CR_USE_CODE_BASE_DM_SHIFT 24
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
-#endif
+#endif /* _SGX540DEFS_KM_H_ */
diff --git a/sgx/services4/srvkm/hwdefs/sgx544defs.h b/sgx/services4/srvkm/hwdefs/sgx544defs.h
index c18b8ad..c35a259 100644
--- a/sgx/services4/srvkm/hwdefs/sgx544defs.h
+++ b/sgx/services4/srvkm/hwdefs/sgx544defs.h
@@ -1,32 +1,49 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGX544.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _SGX544DEFS_KM_H_
#define _SGX544DEFS_KM_H_
+/* Register EUR_CR_CLKGATECTL */
#define EUR_CR_CLKGATECTL 0x0000
#define EUR_CR_CLKGATECTL_ISP_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL_ISP_CLKG_SHIFT 0
@@ -67,6 +84,7 @@
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_MASK 0x10000000U
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SHIFT 28
#define EUR_CR_CLKGATECTL_SYSTEM_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATECTL2 */
#define EUR_CR_CLKGATECTL2 0x0004
#define EUR_CR_CLKGATECTL2_PBE_CLKG_MASK 0x00000003U
#define EUR_CR_CLKGATECTL2_PBE_CLKG_SHIFT 0
@@ -104,6 +122,7 @@
#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_MASK 0x0C000000U
#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SHIFT 26
#define EUR_CR_CLKGATECTL2_DCU0_L0L1_CLKG_SIGNED 0
+/* Register EUR_CR_CLKGATESTATUS */
#define EUR_CR_CLKGATESTATUS 0x0008
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_MASK 0x00000001U
#define EUR_CR_CLKGATESTATUS_ISP_CLKS_SHIFT 0
@@ -174,6 +193,7 @@
#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_MASK 0x01000000U
#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SHIFT 24
#define EUR_CR_CLKGATESTATUS_BIF_CORE_CLKS_SIGNED 0
+/* Register EUR_CR_CLKGATECTLOVR */
#define EUR_CR_CLKGATECTLOVR 0x000C
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_MASK 0x00000003U
#define EUR_CR_CLKGATECTLOVR_ISP_CLKO_SHIFT 0
@@ -208,10 +228,12 @@
#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_MASK 0x00300000U
#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SHIFT 20
#define EUR_CR_CLKGATECTLOVR_BIF_CORE_CLKO_SIGNED 0
+/* Register EUR_CR_POWER */
#define EUR_CR_POWER 0x001C
#define EUR_CR_POWER_PIPE_DISABLE_MASK 0x00000001U
#define EUR_CR_POWER_PIPE_DISABLE_SHIFT 0
#define EUR_CR_POWER_PIPE_DISABLE_SIGNED 0
+/* Register EUR_CR_CORE_ID */
#define EUR_CR_CORE_ID 0x0020
#define EUR_CR_CORE_ID_CONFIG_MULTI_MASK 0x00000001U
#define EUR_CR_CORE_ID_CONFIG_MULTI_SHIFT 0
@@ -231,6 +253,7 @@
#define EUR_CR_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_CORE_ID_ID_SHIFT 16
#define EUR_CR_CORE_ID_ID_SIGNED 0
+/* Register EUR_CR_CORE_REVISION */
#define EUR_CR_CORE_REVISION 0x0024
#define EUR_CR_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_CORE_REVISION_MAINTENANCE_SHIFT 0
@@ -244,14 +267,17 @@
#define EUR_CR_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_CORE_REVISION_DESIGNER_SHIFT 24
#define EUR_CR_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD1 */
#define EUR_CR_DESIGNER_REV_FIELD1 0x0028
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SHIFT 0
#define EUR_CR_DESIGNER_REV_FIELD1_DESIGNER_REV_FIELD1_SIGNED 0
+/* Register EUR_CR_DESIGNER_REV_FIELD2 */
#define EUR_CR_DESIGNER_REV_FIELD2 0x002C
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_MASK 0xFFFFFFFFU
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SHIFT 0
#define EUR_CR_DESIGNER_REV_FIELD2_DESIGNER_REV_FIELD2_SIGNED 0
+/* Register EUR_CR_SOFT_RESET */
#define EUR_CR_SOFT_RESET 0x0080
#define EUR_CR_SOFT_RESET_BIF_RESET_MASK 0x00000001U
#define EUR_CR_SOFT_RESET_BIF_RESET_SHIFT 0
@@ -310,6 +336,7 @@
#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_MASK 0x00080000U
#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SHIFT 19
#define EUR_CR_SOFT_RESET_DCU_L0L1_RESET_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE2 */
#define EUR_CR_EVENT_HOST_ENABLE2 0x0110
#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
#define EUR_CR_EVENT_HOST_ENABLE2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
@@ -347,6 +374,7 @@
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SHIFT 0
#define EUR_CR_EVENT_HOST_ENABLE2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR2 */
#define EUR_CR_EVENT_HOST_CLEAR2 0x0114
#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
#define EUR_CR_EVENT_HOST_CLEAR2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
@@ -384,6 +412,7 @@
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SHIFT 0
#define EUR_CR_EVENT_HOST_CLEAR2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS2 */
#define EUR_CR_EVENT_STATUS2 0x0118
#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_MASK 0x00000800U
#define EUR_CR_EVENT_STATUS2_DATA_BREAKPOINT_UNTRAPPED_SHIFT 11
@@ -421,6 +450,7 @@
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SHIFT 0
#define EUR_CR_EVENT_STATUS2_DPM_TA_FREE_LOAD_SIGNED 0
+/* Register EUR_CR_EVENT_STATUS */
#define EUR_CR_EVENT_STATUS 0x012C
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_STATUS_MASTER_INTERRUPT_SHIFT 31
@@ -506,6 +536,7 @@
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SHIFT 0
#define EUR_CR_EVENT_STATUS_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_ENABLE */
#define EUR_CR_EVENT_HOST_ENABLE 0x0130
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_ENABLE_MASTER_INTERRUPT_SHIFT 31
@@ -591,6 +622,7 @@
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SHIFT 0
#define EUR_CR_EVENT_HOST_ENABLE_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_EVENT_HOST_CLEAR */
#define EUR_CR_EVENT_HOST_CLEAR 0x0134
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_MASK 0x80000000U
#define EUR_CR_EVENT_HOST_CLEAR_MASTER_INTERRUPT_SHIFT 31
@@ -676,26 +708,32 @@
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_MASK 0x00000001U
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SHIFT 0
#define EUR_CR_EVENT_HOST_CLEAR_DPM_3D_MEM_FREE_SIGNED 0
+/* Register EUR_CR_TIMER */
#define EUR_CR_TIMER 0x0144
#define EUR_CR_TIMER_VALUE_MASK 0xFFFFFFFFU
#define EUR_CR_TIMER_VALUE_SHIFT 0
#define EUR_CR_TIMER_VALUE_SIGNED 0
+/* Register EUR_CR_EVENT_KICK1 */
#define EUR_CR_EVENT_KICK1 0x0AB0
#define EUR_CR_EVENT_KICK1_NOW_MASK 0x000000FFU
#define EUR_CR_EVENT_KICK1_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK1_NOW_SIGNED 0
+/* Register EUR_CR_EVENT_KICK2 */
#define EUR_CR_EVENT_KICK2 0x0AC0
#define EUR_CR_EVENT_KICK2_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK2_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK2_NOW_SIGNED 0
+/* Register EUR_CR_EVENT_KICKER */
#define EUR_CR_EVENT_KICKER 0x0AC4
#define EUR_CR_EVENT_KICKER_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_EVENT_KICKER_ADDRESS_SHIFT 4
#define EUR_CR_EVENT_KICKER_ADDRESS_SIGNED 0
+/* Register EUR_CR_EVENT_KICK */
#define EUR_CR_EVENT_KICK 0x0AC8
#define EUR_CR_EVENT_KICK_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK_NOW_SIGNED 0
+/* Register EUR_CR_EVENT_TIMER */
#define EUR_CR_EVENT_TIMER 0x0ACC
#define EUR_CR_EVENT_TIMER_ENABLE_MASK 0x01000000U
#define EUR_CR_EVENT_TIMER_ENABLE_SHIFT 24
@@ -703,26 +741,32 @@
#define EUR_CR_EVENT_TIMER_VALUE_MASK 0x00FFFFFFU
#define EUR_CR_EVENT_TIMER_VALUE_SHIFT 0
#define EUR_CR_EVENT_TIMER_VALUE_SIGNED 0
+/* Register EUR_CR_PDS_INV0 */
#define EUR_CR_PDS_INV0 0x0AD0
#define EUR_CR_PDS_INV0_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV0_DSC_SHIFT 0
#define EUR_CR_PDS_INV0_DSC_SIGNED 0
+/* Register EUR_CR_PDS_INV1 */
#define EUR_CR_PDS_INV1 0x0AD4
#define EUR_CR_PDS_INV1_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV1_DSC_SHIFT 0
#define EUR_CR_PDS_INV1_DSC_SIGNED 0
+/* Register EUR_CR_EVENT_KICK3 */
#define EUR_CR_EVENT_KICK3 0x0AD8
#define EUR_CR_EVENT_KICK3_NOW_MASK 0x00000001U
#define EUR_CR_EVENT_KICK3_NOW_SHIFT 0
#define EUR_CR_EVENT_KICK3_NOW_SIGNED 0
+/* Register EUR_CR_PDS_INV3 */
#define EUR_CR_PDS_INV3 0x0ADC
#define EUR_CR_PDS_INV3_DSC_MASK 0x00000001U
#define EUR_CR_PDS_INV3_DSC_SHIFT 0
#define EUR_CR_PDS_INV3_DSC_SIGNED 0
+/* Register EUR_CR_PDS_INV_CSC */
#define EUR_CR_PDS_INV_CSC 0x0AE0
#define EUR_CR_PDS_INV_CSC_KICK_MASK 0x00000001U
#define EUR_CR_PDS_INV_CSC_KICK_SHIFT 0
#define EUR_CR_PDS_INV_CSC_KICK_SIGNED 0
+/* Register EUR_CR_BIF_CTRL */
#define EUR_CR_BIF_CTRL 0x0C00
#define EUR_CR_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_BIF_CTRL_NOREORDER_SHIFT 0
@@ -763,6 +807,7 @@
#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
#define EUR_CR_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_BIF_INT_STAT */
#define EUR_CR_BIF_INT_STAT 0x0C04
#define EUR_CR_BIF_INT_STAT_FAULT_REQ_MASK 0x00003FFFU
#define EUR_CR_BIF_INT_STAT_FAULT_REQ_SHIFT 0
@@ -773,6 +818,7 @@
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_MASK 0x00080000U
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SHIFT 19
#define EUR_CR_BIF_INT_STAT_FLUSH_COMPLETE_SIGNED 0
+/* Register EUR_CR_BIF_FAULT */
#define EUR_CR_BIF_FAULT 0x0C08
#define EUR_CR_BIF_FAULT_CID_MASK 0x0000000FU
#define EUR_CR_BIF_FAULT_CID_SHIFT 0
@@ -783,6 +829,7 @@
#define EUR_CR_BIF_FAULT_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_FAULT_ADDR_SHIFT 12
#define EUR_CR_BIF_FAULT_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TILE0 */
#define EUR_CR_BIF_TILE0 0x0C0C
#define EUR_CR_BIF_TILE0_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE0_MIN_ADDRESS_SHIFT 0
@@ -793,6 +840,7 @@
#define EUR_CR_BIF_TILE0_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE0_CFG_SHIFT 24
#define EUR_CR_BIF_TILE0_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE1 */
#define EUR_CR_BIF_TILE1 0x0C10
#define EUR_CR_BIF_TILE1_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE1_MIN_ADDRESS_SHIFT 0
@@ -803,6 +851,7 @@
#define EUR_CR_BIF_TILE1_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE1_CFG_SHIFT 24
#define EUR_CR_BIF_TILE1_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE2 */
#define EUR_CR_BIF_TILE2 0x0C14
#define EUR_CR_BIF_TILE2_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE2_MIN_ADDRESS_SHIFT 0
@@ -813,6 +862,7 @@
#define EUR_CR_BIF_TILE2_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE2_CFG_SHIFT 24
#define EUR_CR_BIF_TILE2_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE3 */
#define EUR_CR_BIF_TILE3 0x0C18
#define EUR_CR_BIF_TILE3_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE3_MIN_ADDRESS_SHIFT 0
@@ -823,6 +873,7 @@
#define EUR_CR_BIF_TILE3_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE3_CFG_SHIFT 24
#define EUR_CR_BIF_TILE3_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE4 */
#define EUR_CR_BIF_TILE4 0x0C1C
#define EUR_CR_BIF_TILE4_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE4_MIN_ADDRESS_SHIFT 0
@@ -833,6 +884,7 @@
#define EUR_CR_BIF_TILE4_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE4_CFG_SHIFT 24
#define EUR_CR_BIF_TILE4_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE5 */
#define EUR_CR_BIF_TILE5 0x0C20
#define EUR_CR_BIF_TILE5_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE5_MIN_ADDRESS_SHIFT 0
@@ -843,6 +895,7 @@
#define EUR_CR_BIF_TILE5_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE5_CFG_SHIFT 24
#define EUR_CR_BIF_TILE5_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE6 */
#define EUR_CR_BIF_TILE6 0x0C24
#define EUR_CR_BIF_TILE6_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE6_MIN_ADDRESS_SHIFT 0
@@ -853,6 +906,7 @@
#define EUR_CR_BIF_TILE6_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE6_CFG_SHIFT 24
#define EUR_CR_BIF_TILE6_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE7 */
#define EUR_CR_BIF_TILE7 0x0C28
#define EUR_CR_BIF_TILE7_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE7_MIN_ADDRESS_SHIFT 0
@@ -863,6 +917,7 @@
#define EUR_CR_BIF_TILE7_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE7_CFG_SHIFT 24
#define EUR_CR_BIF_TILE7_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE8 */
#define EUR_CR_BIF_TILE8 0x0C2C
#define EUR_CR_BIF_TILE8_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE8_MIN_ADDRESS_SHIFT 0
@@ -873,6 +928,7 @@
#define EUR_CR_BIF_TILE8_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE8_CFG_SHIFT 24
#define EUR_CR_BIF_TILE8_CFG_SIGNED 0
+/* Register EUR_CR_BIF_TILE9 */
#define EUR_CR_BIF_TILE9 0x0C30
#define EUR_CR_BIF_TILE9_MIN_ADDRESS_MASK 0x00000FFFU
#define EUR_CR_BIF_TILE9_MIN_ADDRESS_SHIFT 0
@@ -883,6 +939,7 @@
#define EUR_CR_BIF_TILE9_CFG_MASK 0x0F000000U
#define EUR_CR_BIF_TILE9_CFG_SHIFT 24
#define EUR_CR_BIF_TILE9_CFG_SIGNED 0
+/* Register EUR_CR_BIF_CTRL_INVAL */
#define EUR_CR_BIF_CTRL_INVAL 0x0C34
#define EUR_CR_BIF_CTRL_INVAL_PTE_MASK 0x00000004U
#define EUR_CR_BIF_CTRL_INVAL_PTE_SHIFT 2
@@ -890,34 +947,42 @@
#define EUR_CR_BIF_CTRL_INVAL_ALL_MASK 0x00000008U
#define EUR_CR_BIF_CTRL_INVAL_ALL_SHIFT 3
#define EUR_CR_BIF_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE1 */
#define EUR_CR_BIF_DIR_LIST_BASE1 0x0C38
#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE1_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE2 */
#define EUR_CR_BIF_DIR_LIST_BASE2 0x0C3C
#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE2_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE3 */
#define EUR_CR_BIF_DIR_LIST_BASE3 0x0C40
#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE3_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE4 */
#define EUR_CR_BIF_DIR_LIST_BASE4 0x0C44
#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE4_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE5 */
#define EUR_CR_BIF_DIR_LIST_BASE5 0x0C48
#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE5_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE6 */
#define EUR_CR_BIF_DIR_LIST_BASE6 0x0C4C
#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE6_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE7 */
#define EUR_CR_BIF_DIR_LIST_BASE7 0x0C50
#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE7_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_SET */
#define EUR_CR_BIF_BANK_SET 0x0C74
#define EUR_CR_BIF_BANK_SET_SELECT_2D_MASK 0x00000001U
#define EUR_CR_BIF_BANK_SET_SELECT_2D_SHIFT 0
@@ -937,6 +1002,7 @@
#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_MASK 0x00000200U
#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SHIFT 9
#define EUR_CR_BIF_BANK_SET_SELECT_DPM_LSS_SIGNED 0
+/* Register EUR_CR_BIF_BANK0 */
#define EUR_CR_BIF_BANK0 0x0C78
#define EUR_CR_BIF_BANK0_INDEX_EDM_MASK 0x0000000FU
#define EUR_CR_BIF_BANK0_INDEX_EDM_SHIFT 0
@@ -950,6 +1016,7 @@
#define EUR_CR_BIF_BANK0_INDEX_PTLA_MASK 0x000F0000U
#define EUR_CR_BIF_BANK0_INDEX_PTLA_SHIFT 16
#define EUR_CR_BIF_BANK0_INDEX_PTLA_SIGNED 0
+/* Register EUR_CR_BIF_BANK1 */
#define EUR_CR_BIF_BANK1 0x0C7C
#define EUR_CR_BIF_BANK1_INDEX_EDM_MASK 0x0000000FU
#define EUR_CR_BIF_BANK1_INDEX_EDM_SHIFT 0
@@ -960,26 +1027,32 @@
#define EUR_CR_BIF_BANK1_INDEX_3D_MASK 0x0000F000U
#define EUR_CR_BIF_BANK1_INDEX_3D_SHIFT 12
#define EUR_CR_BIF_BANK1_INDEX_3D_SIGNED 0
+/* Register EUR_CR_BIF_DIR_LIST_BASE0 */
#define EUR_CR_BIF_DIR_LIST_BASE0 0x0C84
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_MASK 0xFFFFF000U
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SHIFT 12
#define EUR_CR_BIF_DIR_LIST_BASE0_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_TA_REQ_BASE */
#define EUR_CR_BIF_TA_REQ_BASE 0x0C90
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_MASK 0xFFF00000U
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SHIFT 20
#define EUR_CR_BIF_TA_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_MEM_REQ_STAT */
#define EUR_CR_BIF_MEM_REQ_STAT 0x0CA8
#define EUR_CR_BIF_MEM_REQ_STAT_READS_MASK 0x000000FFU
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SHIFT 0
#define EUR_CR_BIF_MEM_REQ_STAT_READS_SIGNED 0
+/* Register EUR_CR_BIF_3D_REQ_BASE */
#define EUR_CR_BIF_3D_REQ_BASE 0x0CAC
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_MASK 0xFFF00000U
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SHIFT 20
#define EUR_CR_BIF_3D_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_ZLS_REQ_BASE */
#define EUR_CR_BIF_ZLS_REQ_BASE 0x0CB0
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_MASK 0xFFF00000U
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SHIFT 20
#define EUR_CR_BIF_ZLS_REQ_BASE_ADDR_SIGNED 0
+/* Register EUR_CR_BIF_BANK_STATUS */
#define EUR_CR_BIF_BANK_STATUS 0x0CB4
#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_MASK 0x00000001U
#define EUR_CR_BIF_BANK_STATUS_3D_CURRENT_BANK_SHIFT 0
@@ -987,6 +1060,7 @@
#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_MASK 0x00000002U
#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SHIFT 1
#define EUR_CR_BIF_BANK_STATUS_TA_CURRENT_BANK_SIGNED 0
+/* Register EUR_CR_BIF_MMU_CTRL */
#define EUR_CR_BIF_MMU_CTRL 0x0CD0
#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
#define EUR_CR_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
@@ -1003,6 +1077,7 @@
#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_MASK 0x00000020U
#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SHIFT 5
#define EUR_CR_BIF_MMU_CTRL_DISABLE_BURST_EXP_SIGNED 0
+/* Register EUR_CR_2D_BLIT_STATUS */
#define EUR_CR_2D_BLIT_STATUS 0x0E04
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_MASK 0x00FFFFFFU
#define EUR_CR_2D_BLIT_STATUS_COMPLETE_SHIFT 0
@@ -1010,6 +1085,7 @@
#define EUR_CR_2D_BLIT_STATUS_BUSY_MASK 0x01000000U
#define EUR_CR_2D_BLIT_STATUS_BUSY_SHIFT 24
#define EUR_CR_2D_BLIT_STATUS_BUSY_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_0 */
#define EUR_CR_2D_VIRTUAL_FIFO_0 0x0E10
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_MASK 0x00000001U
#define EUR_CR_2D_VIRTUAL_FIFO_0_ENABLE_SHIFT 0
@@ -1023,6 +1099,7 @@
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_MASK 0x0000F000U
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SHIFT 12
#define EUR_CR_2D_VIRTUAL_FIFO_0_FLOWRATE_MUL_SIGNED 0
+/* Register EUR_CR_2D_VIRTUAL_FIFO_1 */
#define EUR_CR_2D_VIRTUAL_FIFO_1 0x0E14
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_MASK 0x00000FFFU
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_ACC_SHIFT 0
@@ -1033,14 +1110,17 @@
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_MASK 0xFF000000U
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SHIFT 24
#define EUR_CR_2D_VIRTUAL_FIFO_1_MIN_METRIC_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_START */
#define EUR_CR_BREAKPOINT0_START 0x0F44
#define EUR_CR_BREAKPOINT0_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT0_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT0_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0_END */
#define EUR_CR_BREAKPOINT0_END 0x0F48
#define EUR_CR_BREAKPOINT0_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT0_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT0_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT0 */
#define EUR_CR_BREAKPOINT0 0x0F4C
#define EUR_CR_BREAKPOINT0_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT0_MASK_DM_SHIFT 3
@@ -1054,14 +1134,17 @@
#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT0_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_START */
#define EUR_CR_BREAKPOINT1_START 0x0F50
#define EUR_CR_BREAKPOINT1_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT1_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT1_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1_END */
#define EUR_CR_BREAKPOINT1_END 0x0F54
#define EUR_CR_BREAKPOINT1_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT1_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT1_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT1 */
#define EUR_CR_BREAKPOINT1 0x0F58
#define EUR_CR_BREAKPOINT1_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT1_MASK_DM_SHIFT 3
@@ -1075,14 +1158,17 @@
#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT1_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_START */
#define EUR_CR_BREAKPOINT2_START 0x0F5C
#define EUR_CR_BREAKPOINT2_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT2_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT2_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2_END */
#define EUR_CR_BREAKPOINT2_END 0x0F60
#define EUR_CR_BREAKPOINT2_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT2_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT2_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT2 */
#define EUR_CR_BREAKPOINT2 0x0F64
#define EUR_CR_BREAKPOINT2_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT2_MASK_DM_SHIFT 3
@@ -1096,14 +1182,17 @@
#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT2_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_START */
#define EUR_CR_BREAKPOINT3_START 0x0F68
#define EUR_CR_BREAKPOINT3_START_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT3_START_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT3_START_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3_END */
#define EUR_CR_BREAKPOINT3_END 0x0F6C
#define EUR_CR_BREAKPOINT3_END_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT3_END_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT3_END_ADDRESS_SIGNED 0
+/* Register EUR_CR_BREAKPOINT3 */
#define EUR_CR_BREAKPOINT3 0x0F70
#define EUR_CR_BREAKPOINT3_MASK_DM_MASK 0x00000038U
#define EUR_CR_BREAKPOINT3_MASK_DM_SHIFT 3
@@ -1117,10 +1206,12 @@
#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_MASK 0x00000001U
#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SHIFT 0
#define EUR_CR_BREAKPOINT3_CTRL_RENABLE_SIGNED 0
+/* Register EUR_CR_BREAKPOINT_READ */
#define EUR_CR_BREAKPOINT_READ 0x0F74
#define EUR_CR_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_BREAKPOINT_READ_ADDRESS_SHIFT 4
#define EUR_CR_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP */
#define EUR_CR_PARTITION_BREAKPOINT_TRAP 0x0F78
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
@@ -1128,6 +1219,7 @@
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT */
#define EUR_CR_PARTITION_BREAKPOINT 0x0F7C
#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
#define EUR_CR_PARTITION_BREAKPOINT_MODULE_ID_SHIFT 6
@@ -1141,10 +1233,12 @@
#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_PARTITION_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0 0x0F80
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1 0x0F84
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
@@ -1161,6 +1255,7 @@
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_PARTITION_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_0 */
#define EUR_CR_USE_CODE_BASE_0 0x0A0C
#define EUR_CR_USE_CODE_BASE_ADDR_00_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_00_SHIFT 0
@@ -1168,6 +1263,7 @@
#define EUR_CR_USE_CODE_BASE_DM_00_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_00_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_00_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_1 */
#define EUR_CR_USE_CODE_BASE_1 0x0A10
#define EUR_CR_USE_CODE_BASE_ADDR_01_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_01_SHIFT 0
@@ -1175,6 +1271,7 @@
#define EUR_CR_USE_CODE_BASE_DM_01_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_01_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_01_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_2 */
#define EUR_CR_USE_CODE_BASE_2 0x0A14
#define EUR_CR_USE_CODE_BASE_ADDR_02_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_02_SHIFT 0
@@ -1182,6 +1279,7 @@
#define EUR_CR_USE_CODE_BASE_DM_02_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_02_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_02_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_3 */
#define EUR_CR_USE_CODE_BASE_3 0x0A18
#define EUR_CR_USE_CODE_BASE_ADDR_03_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_03_SHIFT 0
@@ -1189,6 +1287,7 @@
#define EUR_CR_USE_CODE_BASE_DM_03_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_03_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_03_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_4 */
#define EUR_CR_USE_CODE_BASE_4 0x0A1C
#define EUR_CR_USE_CODE_BASE_ADDR_04_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_04_SHIFT 0
@@ -1196,6 +1295,7 @@
#define EUR_CR_USE_CODE_BASE_DM_04_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_04_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_04_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_5 */
#define EUR_CR_USE_CODE_BASE_5 0x0A20
#define EUR_CR_USE_CODE_BASE_ADDR_05_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_05_SHIFT 0
@@ -1203,6 +1303,7 @@
#define EUR_CR_USE_CODE_BASE_DM_05_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_05_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_05_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_6 */
#define EUR_CR_USE_CODE_BASE_6 0x0A24
#define EUR_CR_USE_CODE_BASE_ADDR_06_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_06_SHIFT 0
@@ -1210,6 +1311,7 @@
#define EUR_CR_USE_CODE_BASE_DM_06_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_06_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_06_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_7 */
#define EUR_CR_USE_CODE_BASE_7 0x0A28
#define EUR_CR_USE_CODE_BASE_ADDR_07_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_07_SHIFT 0
@@ -1217,6 +1319,7 @@
#define EUR_CR_USE_CODE_BASE_DM_07_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_07_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_07_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_8 */
#define EUR_CR_USE_CODE_BASE_8 0x0A2C
#define EUR_CR_USE_CODE_BASE_ADDR_08_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_08_SHIFT 0
@@ -1224,6 +1327,7 @@
#define EUR_CR_USE_CODE_BASE_DM_08_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_08_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_08_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_9 */
#define EUR_CR_USE_CODE_BASE_9 0x0A30
#define EUR_CR_USE_CODE_BASE_ADDR_09_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_09_SHIFT 0
@@ -1231,6 +1335,7 @@
#define EUR_CR_USE_CODE_BASE_DM_09_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_09_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_09_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_10 */
#define EUR_CR_USE_CODE_BASE_10 0x0A34
#define EUR_CR_USE_CODE_BASE_ADDR_10_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_10_SHIFT 0
@@ -1238,6 +1343,7 @@
#define EUR_CR_USE_CODE_BASE_DM_10_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_10_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_10_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_11 */
#define EUR_CR_USE_CODE_BASE_11 0x0A38
#define EUR_CR_USE_CODE_BASE_ADDR_11_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_11_SHIFT 0
@@ -1245,6 +1351,7 @@
#define EUR_CR_USE_CODE_BASE_DM_11_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_11_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_11_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_12 */
#define EUR_CR_USE_CODE_BASE_12 0x0A3C
#define EUR_CR_USE_CODE_BASE_ADDR_12_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_12_SHIFT 0
@@ -1252,6 +1359,7 @@
#define EUR_CR_USE_CODE_BASE_DM_12_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_12_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_12_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_13 */
#define EUR_CR_USE_CODE_BASE_13 0x0A40
#define EUR_CR_USE_CODE_BASE_ADDR_13_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_13_SHIFT 0
@@ -1259,6 +1367,7 @@
#define EUR_CR_USE_CODE_BASE_DM_13_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_13_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_13_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_14 */
#define EUR_CR_USE_CODE_BASE_14 0x0A44
#define EUR_CR_USE_CODE_BASE_ADDR_14_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_14_SHIFT 0
@@ -1266,6 +1375,7 @@
#define EUR_CR_USE_CODE_BASE_DM_14_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_14_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_14_SIGNED 0
+/* Register EUR_CR_USE_CODE_BASE_15 */
#define EUR_CR_USE_CODE_BASE_15 0x0A48
#define EUR_CR_USE_CODE_BASE_ADDR_15_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_15_SHIFT 0
@@ -1273,6 +1383,7 @@
#define EUR_CR_USE_CODE_BASE_DM_15_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_15_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_15_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP */
#define EUR_CR_PIPE0_BREAKPOINT_TRAP 0x0F88
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
@@ -1280,6 +1391,7 @@
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT */
#define EUR_CR_PIPE0_BREAKPOINT 0x0F8C
#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
#define EUR_CR_PIPE0_BREAKPOINT_MODULE_ID_SHIFT 6
@@ -1293,10 +1405,12 @@
#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_PIPE0_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0 0x0F90
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1 0x0F94
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
@@ -1313,6 +1427,7 @@
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_PIPE0_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP */
#define EUR_CR_PIPE1_BREAKPOINT_TRAP 0x0F98
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
@@ -1320,6 +1435,7 @@
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT */
#define EUR_CR_PIPE1_BREAKPOINT 0x0F9C
#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_MASK 0x000003C0U
#define EUR_CR_PIPE1_BREAKPOINT_MODULE_ID_SHIFT 6
@@ -1333,10 +1449,12 @@
#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_PIPE1_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0 0x0FA0
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1 0x0FA4
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
@@ -1353,6 +1471,8 @@
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_PIPE1_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Table EUR_CR_USE_CODE_BASE */
+/* Register EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE(X) (0x0A0C + (4 * (X)))
#define EUR_CR_USE_CODE_BASE_ADDR_MASK 0x03FFFFFFU
#define EUR_CR_USE_CODE_BASE_ADDR_SHIFT 0
@@ -1360,8 +1480,9 @@
#define EUR_CR_USE_CODE_BASE_DM_MASK 0x0C000000U
#define EUR_CR_USE_CODE_BASE_DM_SHIFT 26
#define EUR_CR_USE_CODE_BASE_DM_SIGNED 0
+/* Number of entries in table EUR_CR_USE_CODE_BASE */
#define EUR_CR_USE_CODE_BASE_SIZE_UINT32 16
#define EUR_CR_USE_CODE_BASE_NUM_ENTRIES 16
-#endif
+#endif /* _SGX544DEFS_KM_H_ */
diff --git a/sgx/services4/srvkm/hwdefs/sgxdefs.h b/sgx/services4/srvkm/hwdefs/sgxdefs.h
index b3a2583..dee7bce 100644
--- a/sgx/services4/srvkm/hwdefs/sgxdefs.h
+++ b/sgx/services4/srvkm/hwdefs/sgxdefs.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX hw definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _SGXDEFS_H_
#define _SGXDEFS_H_
@@ -79,12 +95,19 @@
#include "sgxmpplusdefs.h"
#else
#include "sgxmpdefs.h"
-#endif
-#else
+#endif /* SGX554 */
+#else /* SGX_FEATURE_MP */
#if defined(SGX_FEATURE_SYSTEM_CACHE)
#include "mnemedefs.h"
#endif
-#endif
+#endif /* SGX_FEATURE_MP */
+
+/*****************************************************************************
+ Core specific defines.
+*****************************************************************************/
-#endif
+#endif /* _SGXDEFS_H_ */
+/*****************************************************************************
+ End of file (sgxdefs.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/hwdefs/sgxerrata.h b/sgx/services4/srvkm/hwdefs/sgxerrata.h
index ccfafd5..36d8b30 100644
--- a/sgx/services4/srvkm/hwdefs/sgxerrata.h
+++ b/sgx/services4/srvkm/hwdefs/sgxerrata.h
@@ -1,215 +1,200 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX HW errata definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Specifies associations between SGX core revisions
+ and SW workarounds required to fix HW errata that exist
+ in specific core revisions
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _SGXERRATA_KM_H_
#define _SGXERRATA_KM_H_
+/* ignore warnings about unrecognised preprocessing directives in conditional inclusion directives */
+/* PRQA S 3115 ++ */
+
#if defined(SGX520) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX520 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 100
- #define FIX_HW_BRN_28889
- #else
#if SGX_CORE_REV == 111
- #define FIX_HW_BRN_28889
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX520 Core Revision unspecified"
#endif
#endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX530) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX530 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 110
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
- #else
- #if SGX_CORE_REV == 111
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
- #else
- #if SGX_CORE_REV == 1111
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
- #else
#if SGX_CORE_REV == 120
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 121
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 125
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 130
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_28889
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_28889/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX530 Core Revision unspecified"
#endif
#endif
#endif
- #endif
- #endif
- #endif
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX531) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX531 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
#if SGX_CORE_REV == 101
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 110
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX531 Core Revision unspecified"
#endif
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if (defined(SGX535) || defined(SGX535_V1_1)) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX535 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 112
- #define FIX_HW_BRN_23281
- #define FIX_HW_BRN_23410
- #define FIX_HW_BRN_22693
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_22997
- #define FIX_HW_BRN_23030
- #else
- #if SGX_CORE_REV == 113
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_23281
- #define FIX_HW_BRN_23944
- #define FIX_HW_BRN_23410
- #else
#if SGX_CORE_REV == 121
- #define FIX_HW_BRN_22934
- #define FIX_HW_BRN_23944
- #define FIX_HW_BRN_23410
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_23944/* Workaround in code (services) */
+ #define FIX_HW_BRN_23410/* Workaround in code (services) and ucode */
#else
#if SGX_CORE_REV == 126
- #define FIX_HW_BRN_22934
+ #define FIX_HW_BRN_22934/* Workaround in sgx featuredefs */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX535 Core Revision unspecified"
#endif
#endif
#endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX540) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX540 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
#if SGX_CORE_REV == 101
- #define FIX_HW_BRN_25499
- #define FIX_HW_BRN_25503
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_25499/* Workaround in sgx featuredefs */
+ #define FIX_HW_BRN_25503/* Workaround in code (services) */
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 110
- #define FIX_HW_BRN_25503
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_25503/* Workaround in code (services) */
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 120
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_26620/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 121
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_28011/* Workaround in services (srvkm) */
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == 130
- #define FIX_HW_BRN_34028
+ #define FIX_HW_BRN_34028/* Workaround in services (srvkm) */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX540 Core Revision unspecified"
#endif
@@ -218,243 +203,145 @@
#endif
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
-#if defined(SGX541) && !defined(SGX_CORE_DEFINED)
- #if defined(SGX_FEATURE_MP)
-
- #define SGX_CORE_REV_HEAD 0
- #if defined(USE_SGX_CORE_REV_HEAD)
-
- #define SGX_CORE_REV SGX_CORE_REV_HEAD
- #endif
-
- #if SGX_CORE_REV == 100
- #define FIX_HW_BRN_27270
- #define FIX_HW_BRN_28011
- #define FIX_HW_BRN_27510
-
- #else
- #if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
- #else
- #error "sgxerrata.h: SGX541 Core Revision unspecified"
- #endif
- #endif
-
- #define SGX_CORE_DEFINED
- #else
- #error "sgxerrata.h: SGX541 only supports MP configs (SGX_FEATURE_MP)"
- #endif
-#endif
#if defined(SGX543) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX543 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 113
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_29997
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #else
#if SGX_CORE_REV == 122
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_29997
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
+ #define FIX_HW_BRN_29997/* workaround in services */
+ #define FIX_HW_BRN_30954/* workaround in services */
+ #define FIX_HW_BRN_31093/* workaround in services */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31620/* workaround in services */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_31542/* workaround in uKernel and Services */
+ #define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 1221
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
-
- #else
- #if SGX_CORE_REV == 140
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
- #define FIX_HW_BRN_33920
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
-
- #else
- #if SGX_CORE_REV == 1401
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_30954
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
- #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_31542/* workaround in uKernel and Services */
+ #define FIX_HW_BRN_31671/* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32044/* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 141
- #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
-
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 142
- #define FIX_HW_BRN_29954
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
-
- #else
- #if SGX_CORE_REV == 211
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
-
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 2111
- #define FIX_HW_BRN_30982
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_30982 /* workaround in uKernel and services */
+ #define FIX_HW_BRN_31093/* workaround in services */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31620/* workaround in services */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_31542/* workaround in uKernel and Services */
+ #define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 213
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #if defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
-
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == 216
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 302
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+// FIXME #define FIX_HW_BRN_36513 /* workaround in uKernel and Services : incomplete for CS and MP1 */
#else
#if SGX_CORE_REV == 303
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+// FIXME #define FIX_HW_BRN_36513 /* workaround in uKernel and Services : incomplete for CS and MP1 */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
#else
#error "sgxerrata.h: SGX543 Core Revision unspecified"
@@ -468,124 +355,84 @@
#endif
#endif
#endif
- #endif
- #endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX544) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX544 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 100
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #else
- #if SGX_CORE_REV == 102
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32085
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #else
- #if SGX_CORE_REV == 103
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32085
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
- #else
#if SGX_CORE_REV == 104
- #define FIX_HW_BRN_29954
- #define FIX_HW_BRN_31093
- #define FIX_HW_BRN_31195
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31278
+ #define FIX_HW_BRN_29954/* turns off regbank split feature */
+ #define FIX_HW_BRN_31093/* workaround in services */
+ #define FIX_HW_BRN_31195/* workaround in services */
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_31278/* disabled prefetching in MMU */
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31542
- #define FIX_HW_BRN_31620
- #define FIX_HW_BRN_31671
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_32044
- #define FIX_HW_BRN_32085
+ #define FIX_HW_BRN_31542 /* workaround in uKernel and Services */
+ #define FIX_HW_BRN_31620/* workaround in services */
+ #define FIX_HW_BRN_31671 /* workaround in uKernel */
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #define FIX_HW_BRN_32044 /* workaround in uKernel, services and client drivers */
+ #define FIX_HW_BRN_32085 /* workaround in services: prefetch fix applied, investigating PT based fix */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 105
#if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
+ #define FIX_HW_BRN_31559/* workaround in services and uKernel */
#endif
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
- #define FIX_HW_BRN_33920
- #else
- #if SGX_CORE_REV == 106
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_31780
- #define FIX_HW_BRN_33920
- #else
- #if SGX_CORE_REV == 110
- #define FIX_HW_BRN_31272
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
- #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
- #endif
- #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == 112
- #define FIX_HW_BRN_31272
- #define FIX_HW_BRN_33920
+ #define FIX_HW_BRN_31272/* workaround in services (srvclient) and uKernel */
+ #define FIX_HW_BRN_33920/* workaround in ukernel */
+// FIXME #define FIX_HW_BRN_36513 /* workaround in uKernel and Services : incomplete for CS and MP1 */
#else
#if SGX_CORE_REV == 114
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
+// FIXME #define FIX_HW_BRN_36513 /* workaround in uKernel and Services : incomplete for CS and MP1 */
#else
#if SGX_CORE_REV == 115
- #if defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_31425
- #endif
- #define FIX_HW_BRN_31780
+ #define FIX_HW_BRN_31780/* workaround in uKernel */
+ #if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
+ #endif
+// FIXME BRN_36513 incomplete for CS and MP1 */
+ #if defined(SGX_FEATURE_MP)
+ #if SGX_FEATURE_MP_CORE_COUNT > 1
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services : incomplete for CS and MP1 */
+ #endif
+ #endif
+ #else
+ #if SGX_CORE_REV == 116
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel */
#endif
+ #define FIX_HW_BRN_33809/* workaround in kernel (enable burst combiner) */
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
#else
#error "sgxerrata.h: SGX544 Core Revision unspecified"
@@ -596,39 +443,22 @@
#endif
#endif
#endif
- #endif
- #endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX545) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX545 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
- #if SGX_CORE_REV == 100
- #define FIX_HW_BRN_26620
- #define FIX_HW_BRN_27266
- #define FIX_HW_BRN_27456
- #define FIX_HW_BRN_29702
- #define FIX_HW_BRN_29823
- #else
#if SGX_CORE_REV == 109
- #define FIX_HW_BRN_29702
- #define FIX_HW_BRN_29823
- #define FIX_HW_BRN_31939
- #else
- #if SGX_CORE_REV == 1012
- #define FIX_HW_BRN_31939
- #else
- #if SGX_CORE_REV == 1013
- #define FIX_HW_BRN_31939
+ #define FIX_HW_BRN_29702/* Workaround in services */
+ #define FIX_HW_BRN_29823/* Workaround in services */
+ #define FIX_HW_BRN_31939/* workaround in uKernel */
#else
#if SGX_CORE_REV == 10131
#else
@@ -637,7 +467,7 @@
#if SGX_CORE_REV == 10141
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
-
+ /* RTL head - no BRNs to apply */
#else
#error "sgxerrata.h: SGX545 Core Revision unspecified"
#endif
@@ -645,36 +475,34 @@
#endif
#endif
#endif
- #endif
- #endif
- #endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
#if defined(SGX554) && !defined(SGX_CORE_DEFINED)
-
+ /* define the _current_ SGX554 RTL head revision */
#define SGX_CORE_REV_HEAD 0
#if defined(USE_SGX_CORE_REV_HEAD)
-
+ /* build config selects Core Revision to be the Head */
#define SGX_CORE_REV SGX_CORE_REV_HEAD
#endif
#if SGX_CORE_REV == 1251
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
-
+ #define FIX_HW_BRN_36513 /* workaround in uKernel and Services */
+ /* add BRNs here */
#else
#if SGX_CORE_REV == SGX_CORE_REV_HEAD
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && defined(SGX_FEATURE_MP)
- #define FIX_HW_BRN_33657
+ #define FIX_HW_BRN_33657/* workaround in ukernel*/
#endif
#else
#error "sgxerrata.h: SGX554 Core Revision unspecified"
#endif
#endif
-
+ /* signal that the Core Version has a valid definition */
#define SGX_CORE_DEFINED
#endif
@@ -686,5 +514,11 @@
#endif
#endif
-#endif
+/* restore warning */
+/* PRQA S 3115 -- */
+
+#endif /* _SGXERRATA_KM_H_ */
+/******************************************************************************
+ End of file (sgxerrata.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/hwdefs/sgxfeaturedefs.h b/sgx/services4/srvkm/hwdefs/sgxfeaturedefs.h
index 6427e7e..cefa154 100644
--- a/sgx/services4/srvkm/hwdefs/sgxfeaturedefs.h
+++ b/sgx/services4/srvkm/hwdefs/sgxfeaturedefs.h
@@ -1,29 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX fexture definitions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if defined(SGX520)
#define SGX_CORE_FRIENDLY_NAME "SGX520"
#define SGX_CORE_ID SGX_CORE_ID_520
@@ -105,13 +120,18 @@
#define SGX_FEATURE_AUTOCLOCKGATING
#define SGX_FEATURE_MONOLITHIC_UKERNEL
#define SGX_FEATURE_MULTI_EVENT_KICK
+// #define SGX_FEATURE_DATA_BREAKPOINTS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES (2)
+// #define SGX_FEATURE_2D_HARDWARE
+// #define SGX_FEATURE_PTLA
#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING)
#if defined(SGX_FEATURE_MP)
#define SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH
- #endif
#define SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH
+ #endif
#define SGX_FEATURE_SW_ISP_CONTEXT_SWITCH
#endif
#else
@@ -136,8 +156,8 @@
#define SGX_FEATURE_MAX_TA_RENDER_TARGETS (512)
#define SGX_FEATURE_SECONDARY_REQUIRES_USE_KICK
#define SGX_FEATURE_WRITEBACK_DCU
-
-
+ //FIXME: this is defined in the build config for now
+ //#define SGX_FEATURE_36BIT_MMU
#define SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
#define SGX_FEATURE_MULTI_EVENT_KICK
#define SGX_FEATURE_EDM_VERTEX_PDSADDR_FULL_RANGE
@@ -157,6 +177,9 @@
#define SGX_FEATURE_AUTOCLOCKGATING
#define SGX_FEATURE_MONOLITHIC_UKERNEL
#define SGX_FEATURE_MULTI_EVENT_KICK
+// #define SGX_FEATURE_DATA_BREAKPOINTS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS
+// #define SGX_FEATURE_PERPIPE_BKPT_REGS_NUMPIPES (2)
#define SGX_FEATURE_2D_HARDWARE
#define SGX_FEATURE_PTLA
#define SGX_FEATURE_EXTENDED_PERF_COUNTERS
@@ -180,21 +203,18 @@
#if defined(SGX_FEATURE_SLAVE_VDM_CONTEXT_SWITCH) \
|| defined(SGX_FEATURE_MASTER_VDM_CONTEXT_SWITCH)
+/* Enable the define so common code for HW VDMCS code is compiled */
#define SGX_FEATURE_VDM_CONTEXT_SWITCH
#endif
-#if defined(FIX_HW_BRN_22693)
-#undef SGX_FEATURE_AUTOCLOCKGATING
-#endif
+/*
+ 'switch-off' features if defined BRNs affect the feature
+*/
#if defined(FIX_HW_BRN_27266)
#undef SGX_FEATURE_36BIT_MMU
#endif
-#if defined(FIX_HW_BRN_27456)
-#undef SGX_FEATURE_BIF_WIDE_TILING_AND_4K_ADDRESS
-#endif
-
#if defined(FIX_HW_BRN_22934) \
|| defined(FIX_HW_BRN_25499)
#undef SGX_FEATURE_MULTI_EVENT_KICK
@@ -218,11 +238,16 @@
#undef SGX_FEATURE_BIF_NUM_DIRLISTS
#endif
+/*
+ Derive other definitions:
+*/
+
+/* define default MP core count */
#if defined(SGX_FEATURE_MP)
#if defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D)
#if (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D)
#error Number of TA cores larger than number of 3D cores not supported in current driver
-#endif
+#endif /* (SGX_FEATURE_MP_CORE_COUNT_TA > SGX_FEATURE_MP_CORE_COUNT_3D) */
#else
#if defined(SGX_FEATURE_MP_CORE_COUNT)
#define SGX_FEATURE_MP_CORE_COUNT_TA (SGX_FEATURE_MP_CORE_COUNT)
@@ -231,13 +256,13 @@
#error Either SGX_FEATURE_MP_CORE_COUNT or \
both SGX_FEATURE_MP_CORE_COUNT_TA and SGX_FEATURE_MP_CORE_COUNT_3D \
must be defined when SGX_FEATURE_MP is defined
-#endif
-#endif
+#endif /* SGX_FEATURE_MP_CORE_COUNT */
+#endif /* defined(SGX_FEATURE_MP_CORE_COUNT_TA) && defined(SGX_FEATURE_MP_CORE_COUNT_3D) */
#else
#define SGX_FEATURE_MP_CORE_COUNT (1)
#define SGX_FEATURE_MP_CORE_COUNT_TA (1)
#define SGX_FEATURE_MP_CORE_COUNT_3D (1)
-#endif
+#endif /* SGX_FEATURE_MP */
#if defined(SUPPORT_SGX_LOW_LATENCY_SCHEDULING) && !defined(SUPPORT_SGX_PRIORITY_SCHEDULING)
#define SUPPORT_SGX_PRIORITY_SCHEDULING
@@ -245,3 +270,6 @@ must be defined when SGX_FEATURE_MP is defined
#include "img_types.h"
+/******************************************************************************
+ End of file (sgxfeaturedefs.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/hwdefs/sgxmmu.h b/sgx/services4/srvkm/hwdefs/sgxmmu.h
index 1b265f1..509fa5a 100644
--- a/sgx/services4/srvkm/hwdefs/sgxmmu.h
+++ b/sgx/services4/srvkm/hwdefs/sgxmmu.h
@@ -1,40 +1,62 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title SGX MMU defines
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provides SGX MMU declarations and macros
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#if !defined(__SGXMMU_KM_H__)
#define __SGXMMU_KM_H__
+/* to be implemented */
+
+/* SGX MMU maps 4Kb pages */
#define SGX_MMU_PAGE_SHIFT (12)
#define SGX_MMU_PAGE_SIZE (1U<<SGX_MMU_PAGE_SHIFT)
#define SGX_MMU_PAGE_MASK (SGX_MMU_PAGE_SIZE - 1U)
+/* PD details */
#define SGX_MMU_PD_SHIFT (10)
#define SGX_MMU_PD_SIZE (1U<<SGX_MMU_PD_SHIFT)
#define SGX_MMU_PD_MASK (0xFFC00000U)
+/* PD Entry details */
#if defined(SGX_FEATURE_36BIT_MMU)
#define SGX_MMU_PDE_ADDR_MASK (0xFFFFFF00U)
#define SGX_MMU_PDE_ADDR_ALIGNSHIFT (4)
@@ -43,6 +65,7 @@
#define SGX_MMU_PDE_ADDR_ALIGNSHIFT (0)
#endif
#define SGX_MMU_PDE_VALID (0x00000001U)
+/* variable page size control field */
#define SGX_MMU_PDE_PAGE_SIZE_4K (0x00000000U)
#define SGX_MMU_PDE_PAGE_SIZE_16K (0x00000002U)
#define SGX_MMU_PDE_PAGE_SIZE_64K (0x00000004U)
@@ -51,10 +74,12 @@
#define SGX_MMU_PDE_PAGE_SIZE_4M (0x0000000AU)
#define SGX_MMU_PDE_PAGE_SIZE_MASK (0x0000000EU)
+/* PT details */
#define SGX_MMU_PT_SHIFT (10)
#define SGX_MMU_PT_SIZE (1U<<SGX_MMU_PT_SHIFT)
#define SGX_MMU_PT_MASK (0x003FF000U)
+/* PT Entry details */
#if defined(SGX_FEATURE_36BIT_MMU)
#define SGX_MMU_PTE_ADDR_MASK (0xFFFFFF00U)
#define SGX_MMU_PTE_ADDR_ALIGNSHIFT (4)
@@ -68,5 +93,8 @@
#define SGX_MMU_PTE_CACHECONSISTENT (0x00000008U)
#define SGX_MMU_PTE_EDMPROTECT (0x00000010U)
-#endif
+#endif /* __SGXMMU_KM_H__ */
+/*****************************************************************************
+ End of file (sgxmmu.h)
+*****************************************************************************/
diff --git a/sgx/services4/srvkm/hwdefs/sgxmpdefs.h b/sgx/services4/srvkm/hwdefs/sgxmpdefs.h
index e34561a..4186731 100644
--- a/sgx/services4/srvkm/hwdefs/sgxmpdefs.h
+++ b/sgx/services4/srvkm/hwdefs/sgxmpdefs.h
@@ -1,32 +1,49 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Hardware defs for SGXMP.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
-#ifndef _SGXMPDEFS_H_
-#define _SGXMPDEFS_H_
+The contents of this file are subject to the MIT license as set out below.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+#ifndef _SGXMPDEFS_KM_H_
+#define _SGXMPDEFS_KM_H_
+
+/* Register EUR_CR_MASTER_BIF_CTRL */
#define EUR_CR_MASTER_BIF_CTRL 0x4C00
#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_MASK 0x00000001U
#define EUR_CR_MASTER_BIF_CTRL_NOREORDER_SHIFT 0
@@ -49,6 +66,7 @@
#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_MASK 0x00080000U
#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SHIFT 19
#define EUR_CR_MASTER_BIF_CTRL_MMU_BYPASS_MASTER_DPM_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_CTRL_INVAL */
#define EUR_CR_MASTER_BIF_CTRL_INVAL 0x4C34
#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_MASK 0x00000004U
#define EUR_CR_MASTER_BIF_CTRL_INVAL_PTE_SHIFT 2
@@ -56,6 +74,7 @@
#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_MASK 0x00000008U
#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_SHIFT 3
#define EUR_CR_MASTER_BIF_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_BIF_MMU_CTRL */
#define EUR_CR_MASTER_BIF_MMU_CTRL 0x4CD0
#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_MASK 0x00000001U
#define EUR_CR_MASTER_BIF_MMU_CTRL_PREFETCHING_ON_SHIFT 0
@@ -66,6 +85,7 @@
#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_MASK 0x00000010U
#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_SHIFT 4
#define EUR_CR_MASTER_BIF_MMU_CTRL_ENABLE_DC_TLB_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL */
#define EUR_CR_MASTER_SLC_CTRL 0x4D00
#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_MASK 0x00800000U
#define EUR_CR_MASTER_SLC_CTRL_DISABLE_REORDERING_SHIFT 23
@@ -97,6 +117,7 @@
#define EUR_CR_MASTER_SLC_CTRL_PAUSE_MASK 0x00000100U
#define EUR_CR_MASTER_SLC_CTRL_PAUSE_SHIFT 8
#define EUR_CR_MASTER_SLC_CTRL_PAUSE_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_BYPASS */
#define EUR_CR_MASTER_SLC_CTRL_BYPASS 0x4D04
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_MASK 0x08000000U
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_BYP_CC_N_SHIFT 27
@@ -182,10 +203,12 @@
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_MASK 0x00000001U
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_SHIFT 0
#define EUR_CR_MASTER_SLC_CTRL_BYPASS_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_USSE_INVAL */
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL 0x4D08
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_MASK 0xFFFFFFFFU
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_SHIFT 0
#define EUR_CR_MASTER_SLC_CTRL_USSE_INVAL_ADDR_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_INVAL */
#define EUR_CR_MASTER_SLC_CTRL_INVAL 0x4D28
#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_MASK 0x00000008U
#define EUR_CR_MASTER_SLC_CTRL_INVAL_DM_EVENT_SHIFT 3
@@ -199,6 +222,7 @@
#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_MASK 0x00000001U
#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_SHIFT 0
#define EUR_CR_MASTER_SLC_CTRL_INVAL_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_FLUSH */
#define EUR_CR_MASTER_SLC_CTRL_FLUSH 0x4D2C
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_MASK 0x00000080U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_DM_EVENT_SHIFT 7
@@ -212,6 +236,7 @@
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_MASK 0x00000010U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_SHIFT 4
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_SLC_CTRL_FLUSH_INV */
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV 0x4D34
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_MASK 0x00000080U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_DM_EVENT_SHIFT 7
@@ -225,10 +250,12 @@
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_MASK 0x00000010U
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_SHIFT 4
#define EUR_CR_MASTER_SLC_CTRL_FLUSH_INV_ALL_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_READ */
#define EUR_CR_MASTER_BREAKPOINT_READ 0x4F18
#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_SHIFT 4
#define EUR_CR_MASTER_BREAKPOINT_READ_ADDRESS_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP */
#define EUR_CR_MASTER_BREAKPOINT_TRAP 0x4F1C
#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_MASK 0x00000002U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_CONTINUE_SHIFT 1
@@ -236,6 +263,7 @@
#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_MASK 0x00000001U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_SHIFT 0
#define EUR_CR_MASTER_BREAKPOINT_TRAP_WRNOTIFY_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT */
#define EUR_CR_MASTER_BREAKPOINT 0x4F20
#define EUR_CR_MASTER_BREAKPOINT_ID_MASK 0x00000030U
#define EUR_CR_MASTER_BREAKPOINT_ID_SHIFT 4
@@ -246,10 +274,12 @@
#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_MASK 0x00000004U
#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_SHIFT 2
#define EUR_CR_MASTER_BREAKPOINT_TRAPPED_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0 */
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0 0x4F24
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_MASK 0xFFFFFFF0U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_SHIFT 4
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO0_ADDRESS_SIGNED 0
+/* Register EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1 */
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1 0x4F28
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_MASK 0x00007C00U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_SIZE_SHIFT 10
@@ -266,10 +296,12 @@
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_MASK 0x00000001U
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_SHIFT 0
#define EUR_CR_MASTER_BREAKPOINT_TRAP_INFO1_RNW_SIGNED 0
+/* Register EUR_CR_MASTER_CORE */
#define EUR_CR_MASTER_CORE 0x4000
#define EUR_CR_MASTER_CORE_ENABLE_MASK 0x00000003U
#define EUR_CR_MASTER_CORE_ENABLE_SHIFT 0
#define EUR_CR_MASTER_CORE_ENABLE_SIGNED 0
+/* Register EUR_CR_MASTER_CORE_ID */
#define EUR_CR_MASTER_CORE_ID 0x4010
#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_MASK 0x00000001U
#define EUR_CR_MASTER_CORE_ID_CONFIG_MULTI_SHIFT 0
@@ -289,6 +321,7 @@
#define EUR_CR_MASTER_CORE_ID_ID_MASK 0xFFFF0000U
#define EUR_CR_MASTER_CORE_ID_ID_SHIFT 16
#define EUR_CR_MASTER_CORE_ID_ID_SIGNED 0
+/* Register EUR_CR_MASTER_CORE_REVISION */
#define EUR_CR_MASTER_CORE_REVISION 0x4014
#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_MASK 0x000000FFU
#define EUR_CR_MASTER_CORE_REVISION_MAINTENANCE_SHIFT 0
@@ -302,6 +335,7 @@
#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_MASK 0xFF000000U
#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_SHIFT 24
#define EUR_CR_MASTER_CORE_REVISION_DESIGNER_SIGNED 0
+/* Register EUR_CR_MASTER_SOFT_RESET */
#define EUR_CR_MASTER_SOFT_RESET 0x4080
#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_MASK(i) (0x00000001U << (0 + ((i) * 1)))
#define EUR_CR_MASTER_SOFT_RESET_CORE_RESET_SHIFT(i) (0 + ((i) * 1))
@@ -328,5 +362,5 @@
#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_SHIFT 10
#define EUR_CR_MASTER_SOFT_RESET_PTLA_RESET_SIGNED 0
-#endif
+#endif /* _SGXMPDEFS_KM_H_ */
diff --git a/sgx/services4/srvkm/include/buffer_manager.h b/sgx/services4/srvkm/include/buffer_manager.h
index 46f5a68..b7440a0 100644
--- a/sgx/services4/srvkm/include/buffer_manager.h
+++ b/sgx/services4/srvkm/include/buffer_manager.h
@@ -1,28 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Buffer Management.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Manages buffers mapped into two virtual memory spaces, host and
+ device and referenced by handles.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _BUFFER_MANAGER_H_
#define _BUFFER_MANAGER_H_
@@ -35,28 +53,37 @@
extern "C"{
#endif
+/* forward reference */
typedef struct _BM_HEAP_ BM_HEAP;
+/*
+ * The mapping structure is used to record relations between CPU virtual,
+ * CPU physical and device virtual addresses for large chunks of memory
+ * from which we have resource-allocator draw our buffers.
+ *
+ * There is one per contiguous pool and one per import from the host OS.
+ */
struct _BM_MAPPING_
{
enum
{
- hm_wrapped = 1,
- hm_wrapped_scatter,
- hm_wrapped_virtaddr,
- hm_wrapped_scatter_virtaddr,
- hm_env,
- hm_contiguous
+ hm_wrapped = 1, /*!< wrapped user supplied contiguous*/
+ hm_wrapped_scatter, /*!< wrapped user supplied scattered */
+ hm_wrapped_virtaddr, /*!< wrapped user supplied contiguous with virtual address*/
+ hm_wrapped_scatter_virtaddr, /*!< wrapped user supplied scattered with virtual address*/
+ hm_env, /*!< obtained from environment */
+ hm_contiguous /*!< contigous arena */
} eCpuMemoryOrigin;
- BM_HEAP *pBMHeap;
- RA_ARENA *pArena;
+ BM_HEAP *pBMHeap; /* which BM heap */
+ RA_ARENA *pArena; /* whence the memory comes */
IMG_CPU_VIRTADDR CpuVAddr;
IMG_CPU_PHYADDR CpuPAddr;
IMG_DEV_VIRTADDR DevVAddr;
IMG_SYS_PHYADDR *psSysAddr;
IMG_SIZE_T uSize;
+ IMG_SIZE_T uSizeVM;
IMG_HANDLE hOSMemHandle;
IMG_UINT32 ui32Flags;
@@ -70,8 +97,20 @@ struct _BM_MAPPING_
* is remapped with the original alignment restrictions.
*/
IMG_UINT32 ui32DevVAddrAlignment;
+
+ /* Sparse mapping data */
+ IMG_UINT32 ui32ChunkSize;
+ IMG_UINT32 ui32NumVirtChunks;
+ IMG_UINT32 ui32NumPhysChunks;
+ IMG_BOOL *pabMapChunk;
};
+/*
+ * The buffer structure handles individual allocations from the user; thus
+ * there is one allocated per call to BM_Alloc and one per call to BM_Wrap.
+ * We record a mapping reference so we know where to return allocated
+ * resources at BM_Free time.
+ */
typedef struct _BM_BUF_
{
IMG_CPU_VIRTADDR *CpuVAddr;
@@ -97,45 +136,101 @@ struct _BM_HEAP_
struct _BM_HEAP_ *psNext;
struct _BM_HEAP_ **ppsThis;
+ /* BIF tile stride for this heap */
+ IMG_UINT32 ui32XTileStride;
};
+/*
+ * The bm-context structure
+ */
struct _BM_CONTEXT_
{
MMU_CONTEXT *psMMUContext;
-
+ /*
+ * Resource allocation arena of dual mapped pages. For devices
+ * where the hardware imposes different constraints on the valid
+ * device virtual address range depending on the use of the buffer
+ * we maintain two allocation arenas, one low address range, the
+ * other high. For devices without such a constrain we do not
+ * create the high arena, instead all allocations come from the
+ * low arena.
+ */
BM_HEAP *psBMHeap;
-
+ /*
+ * The Shared Heaps
+ */
BM_HEAP *psBMSharedHeap;
PVRSRV_DEVICE_NODE *psDeviceNode;
-
+ /*
+ * Hash table management.
+ */
HASH_TABLE *pBufferHash;
-
+ /*
+ * Resman item handle
+ */
IMG_HANDLE hResItem;
IMG_UINT32 ui32RefCount;
-
-
+ /*
+ linked list next pointer
+ */
struct _BM_CONTEXT_ *psNext;
struct _BM_CONTEXT_ **ppsThis;
};
-
-
+/* refcount.c needs to know the internals of this structure */
+typedef struct _XPROC_DATA_{
+ IMG_UINT32 ui32RefCount;
+ IMG_UINT32 ui32AllocFlags;
+ IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32PageSize;
+ RA_ARENA *psArena;
+ IMG_SYS_PHYADDR sSysPAddr;
+ IMG_VOID *pvCpuVAddr;
+ IMG_HANDLE hOSMemHandle;
+} XPROC_DATA;
+
+extern XPROC_DATA gXProcWorkaroundShareData[];
+/*
+ Buffer handle.
+*/
typedef IMG_VOID *BM_HANDLE;
+/** Buffer manager allocation flags.
+ *
+ * Flags passed to BM_Alloc to specify buffer capabilities.
+ *
+ * @defgroup BP Buffer Manager Allocation Flags
+ * @{
+ */
+
+/** Pool number mask. */
#define BP_POOL_MASK 0x7
+/* Request physically contiguous pages of memory */
#define BP_CONTIGUOUS (1 << 3)
#define BP_PARAMBUFFER (1 << 4)
#define BM_MAX_DEVMEM_ARENAS 2
+/** @} */
+
+/**
+ * @Function BM_CreateContext
+ *
+ * @Description
+ *
+ * @Input
+
+ * @Return
+ */
+
IMG_HANDLE
BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_DEV_PHYADDR *psPDDevPAddr,
@@ -143,30 +238,113 @@ BM_CreateContext(PVRSRV_DEVICE_NODE *psDeviceNode,
IMG_BOOL *pbCreated);
+/**
+ * @Function BM_DestroyContext
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Return PVRSRV_ERROR
+ */
PVRSRV_ERROR
BM_DestroyContext (IMG_HANDLE hBMContext,
IMG_BOOL *pbCreated);
+/**
+ * @Function BM_CreateHeap
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Return
+ */
IMG_HANDLE
BM_CreateHeap (IMG_HANDLE hBMContext,
DEVICE_MEMORY_HEAP_INFO *psDevMemHeapInfo);
+/**
+ * @Function BM_DestroyHeap
+ *
+ * @Description
+ *
+ * @Input
+ *
+ * @Return
+ */
IMG_VOID
BM_DestroyHeap (IMG_HANDLE hDevMemHeap);
+/**
+ * @Function BM_Reinitialise
+ *
+ * @Description
+ *
+ * Reinitialises the buffer manager after a power event. Calling this
+ * function will reprogram MMU registers and renable the MMU.
+ *
+ * @Input None
+ * @Return None
+ */
+
IMG_BOOL
BM_Reinitialise (PVRSRV_DEVICE_NODE *psDeviceNode);
+/**
+ * @Function BM_Alloc
+ *
+ * @Description
+ *
+ * Allocate a buffer mapped into both host and device virtual memory
+ * maps.
+ *
+ * @Input uSize - require size in bytes of the buffer.
+ * @Input/Output pui32Flags - bit mask of buffer property flags + recieves heap flags.
+ * @Input uDevVAddrAlignment - required alignment in bytes, or 0.
+ * @Input pvPrivData - private data passed to OS allocator
+ * @Input ui32PrivDataLength - length of private data
+ * @Input ui32ChunkSize - Chunk size
+ * @Input ui32NumVirtChunks - Number of virtual chunks
+ * @Input ui32NumPhysChunks - Number of physical chunks
+ * @Input pabMapChunk - Chunk mapping array
+ * @Output phBuf - receives the buffer handle.
+ * @Return IMG_TRUE - Success, IMG_FALSE - Failed.
+ */
IMG_BOOL
BM_Alloc (IMG_HANDLE hDevMemHeap,
IMG_DEV_VIRTADDR *psDevVAddr,
IMG_SIZE_T uSize,
IMG_UINT32 *pui32Flags,
IMG_UINT32 uDevVAddrAlignment,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
BM_HANDLE *phBuf);
+/**
+ * @Function BM_Wrap
+ *
+ * @Description
+ *
+ * Create a buffer which wraps user provided host physical memory.
+ * The wrapped memory must be page aligned. BM_Wrap will roundup the
+ * size to a multiple of host pages.
+ *
+ * @Input ui32Size - size of memory to wrap.
+ * @Input ui32Offset - Offset into page of memory to wrap.
+ * @Input bPhysContig - Is the wrap physically contiguous.
+ * @Input psSysAddr - list of system physical page addresses of memory to wrap.
+ * @Input pvCPUVAddr - optional CPU kernel virtual address (Page aligned) of memory to wrap.
+ * @Input uFlags - bit mask of buffer property flags.
+ * @Input phBuf - receives the buffer handle.
+ * @Return IMG_TRUE - Success, IMG_FALSE - Failed
+ */
IMG_BOOL
BM_Wrap ( IMG_HANDLE hDevMemHeap,
IMG_SIZE_T ui32Size,
@@ -177,15 +355,20 @@ BM_Wrap ( IMG_HANDLE hDevMemHeap,
IMG_UINT32 *pui32Flags,
BM_HANDLE *phBuf);
+/**
+ * @Function BM_Free
+ *
+ * @Description
+ *
+ * Free a buffer previously allocated via BM_Alloc.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return None.
+ */
IMG_VOID
BM_Free (BM_HANDLE hBuf,
IMG_UINT32 ui32Flags);
-IMG_VOID
-BM_RegisterSmart(BM_HANDLE hBuf, IMG_HANDLE hSmartCache);
-
-IMG_VOID
-BM_UnregisterSmart(BM_HANDLE hBuf, IMG_HANDLE hSmartCache);
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
@@ -194,15 +377,56 @@ IMG_HANDLE BM_GetGEM(BM_HANDLE hBuf);
#endif /* SUPPORT_DRI_DRM_EXTERNAL */
+/**
+ * @Function BM_HandleToCpuVaddr
+ *
+ * @Description
+ *
+ * Retrieve the host virtual address associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ *
+ * @Return buffers host virtual address.
+ */
IMG_CPU_VIRTADDR
BM_HandleToCpuVaddr (BM_HANDLE hBuf);
+/**
+ * @Function BM_HandleToDevVaddr
+ *
+ * @Description
+ *
+ * Retrieve the device virtual address associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return buffers device virtual address.
+ */
IMG_DEV_VIRTADDR
BM_HandleToDevVaddr (BM_HANDLE hBuf);
+/**
+ * @Function BM_HandleToSysPaddr
+ *
+ * @Description
+ *
+ * Retrieve the system physical address associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return buffers device virtual address.
+ */
IMG_SYS_PHYADDR
BM_HandleToSysPaddr (BM_HANDLE hBuf);
+/**
+ * @Function BM_HandleToMemOSHandle
+ *
+ * @Description
+ *
+ * Retrieve the underlying memory handle associated with a buffer.
+ *
+ * @Input hBuf - buffer handle.
+ * @Return An OS Specific memory handle
+ */
IMG_HANDLE
BM_HandleToOSMemHandle (BM_HANDLE hBuf);
@@ -214,34 +438,212 @@ IMG_BOOL
BM_UnmapFromDev(BM_HANDLE hBuf);
+/**
+ * @Function BM_GetPhysPageAddr
+ *
+ * @Description
+ *
+ * Retreive physical address backing dev V address
+ *
+ * @Input psMemInfo
+ * @Input sDevVPageAddr
+ * @Output psDevPAddr
+ * @Return PVRSRV_ERROR
+ */
IMG_VOID BM_GetPhysPageAddr(PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_DEV_VIRTADDR sDevVPageAddr,
IMG_DEV_PHYADDR *psDevPAddr);
+/*!
+******************************************************************************
+ @Function BM_GetMMUContext
+
+ @Description
+ utility function to return the MMU context
+
+ @inputs hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContext(IMG_HANDLE hDevMemHeap);
+/*!
+******************************************************************************
+ @Function BM_GetMMUContextFromMemContext
+
+ @Description
+ utility function to return the MMU context
+
+ @inputs hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU context, else NULL
+**************************************************************************/
MMU_CONTEXT* BM_GetMMUContextFromMemContext(IMG_HANDLE hDevMemContext);
+/*!
+******************************************************************************
+ @Function BM_GetMMUHeap
+
+ @Description
+ utility function to return the MMU heap handle
+
+ @inputs hDevMemHeap - the Dev mem heap handle
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMMUHeap(IMG_HANDLE hDevMemHeap);
+/*!
+******************************************************************************
+ @Function BM_GetDeviceNode
+
+ @Description utility function to return the devicenode from the BM Context
+
+ @inputs hDevMemContext - the Dev Mem Context
+
+ @Return MMU heap handle, else NULL
+**************************************************************************/
PVRSRV_DEVICE_NODE* BM_GetDeviceNode(IMG_HANDLE hDevMemContext);
+/*!
+******************************************************************************
+ @Function BM_GetMappingHandle
+
+ @Description utility function to return the mapping handle from a meminfo
+
+ @inputs psMemInfo - kernel meminfo
+
+ @Return mapping handle, else NULL
+**************************************************************************/
IMG_HANDLE BM_GetMappingHandle(PVRSRV_KERNEL_MEM_INFO *psMemInfo);
+/*!
+******************************************************************************
+ @Function BM_Export
+
+ @Description Export a buffer previously allocated via BM_Alloc.
+
+ @inputs hBuf - buffer handle.
+
+ @Return None.
+**************************************************************************/
IMG_VOID BM_Export(BM_HANDLE hBuf);
+/*!
+******************************************************************************
+ @Function BM_FreeExport
+
+ @Description Free a buffer previously exported via BM_Export.
+
+ @inputs hBuf - buffer handle.
+ ui32Flags - flags
+
+ @Return None.
+**************************************************************************/
IMG_VOID BM_FreeExport(BM_HANDLE hBuf, IMG_UINT32 ui32Flags);
-PVRSRV_ERROR BM_XProcSetShareIndex(PXProcShareDataNode pShareDataNode);
-PVRSRV_ERROR BM_XProcFinishShareIndex(PXProcShareDataNode pShareDataNode, IMG_BOOL freeIfNotUsed);
-PXProcShareDataNode BM_XProcAllocNewBuffer(void);
+/*!
+******************************************************************************
+ @Function BM_MappingHandleFromBuffer
+
+ @Description utility function to get the BM mapping handle from a BM buffer
+
+ @Input hBuffer - Handle to BM buffer
+
+ @Return BM mapping handle
+**************************************************************************/
+IMG_HANDLE BM_MappingHandleFromBuffer(IMG_HANDLE hBuffer);
+
+/*!
+******************************************************************************
+ @Function BM_GetVirtualSize
+
+ @Description utility function to get the VM size of a BM mapping
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Return VM size of mapping
+**************************************************************************/
+IMG_UINT32 BM_GetVirtualSize(IMG_HANDLE hBMHandle);
+
+/*!
+******************************************************************************
+ @Function BM_MapPageAtOffset
+
+ @Description utility function check if the specificed offset in a BM mapping
+ is a page that needs tp be mapped
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32Offset - Offset into import
+
+ @Return IMG_TRUE if the page should be mapped
+**************************************************************************/
+IMG_BOOL BM_MapPageAtOffset(IMG_HANDLE hBMHandle, IMG_UINT32 ui32Offset);
+
+/*!
+******************************************************************************
+ @Function BM_VirtOffsetToPhyscial
+
+ @Description utility function find of physical offset of a sparse allocation
+ from it's virtual offset.
+
+ @Input hBMHandle - Handle to BM mapping
+
+ @Input ui32VirtOffset - Virtual offset into allocation
+
+ @Output pui32PhysOffset - Physical offset
+
+ @Return IMG_TRUE if the virtual offset is physically backed
+**************************************************************************/
+IMG_BOOL BM_VirtOffsetToPhysical(IMG_HANDLE hBMHandle,
+ IMG_UINT32 ui32VirtOffset,
+ IMG_UINT32 *pui32PhysOffset);
+
+/* The following are present for the "share mem" workaround for
+ cross-process mapping. This is only valid for a specific
+ use-case, and only tested on Linux (Android) and only
+ superficially at that. Do not rely on this API! */
+/* The two "Set" functions set a piece of "global" state in the buffer
+ manager, and "Unset" removes this global state. Therefore, there
+ is no thread-safety here and it's the caller's responsibility to
+ ensure that a mutex is acquired before using these functions or any
+ device memory allocation functions, including, especially,
+ callbacks from RA. */
+/* Once a "Share Index" is set by this means, any requests from the RA
+ to import a block of physical memory shall cause the physical
+ memory allocation to be refcounted, and shared iff the IDs chosen
+ match */
+/* This API is difficult to use, but saves a lot of plumbing in other
+ APIs. The next generation of this library should have this functionality
+ plumbed in properly */
+PVRSRV_ERROR BM_XProcWorkaroundSetShareIndex(IMG_UINT32 ui32Index);
+PVRSRV_ERROR BM_XProcWorkaroundUnsetShareIndex(IMG_UINT32 ui32Index);
+PVRSRV_ERROR BM_XProcWorkaroundFindNewBufferAndSetShareIndex(IMG_UINT32 *pui32Index);
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+IMG_VOID _BM_XProcIndexAcquireDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexReleaseDebug(const IMG_CHAR *pszFile, IMG_INT iLine, IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x...) \
+ _BM_XProcIndexAcquireDebug(__FILE__, __LINE__, x)
+#define BM_XProcIndexRelease(x...) \
+ _BM_XProcIndexReleaseDebug(__FILE__, __LINE__, x)
+
+#else
+IMG_VOID _BM_XProcIndexAcquire(IMG_UINT32 ui32Index);
+IMG_VOID _BM_XProcIndexRelease(IMG_UINT32 ui32Index);
+
+#define BM_XProcIndexAcquire(x) \
+ _BM_XProcIndexAcquire( x)
+#define BM_XProcIndexRelease(x) \
+ _BM_XProcIndexRelease( x)
+#endif
-IMG_UINT32 BM_XProcWorkaroundGetRefCount(IMG_UINT32 ui32Index);
#if defined(__cplusplus)
}
#endif
#endif
-
diff --git a/sgx/services4/srvkm/include/device.h b/sgx/services4/srvkm/include/device.h
index 9df2c73..726d5ce 100644
--- a/sgx/services4/srvkm/include/device.h
+++ b/sgx/services4/srvkm/include/device.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Common Device header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Device related function templates and defines
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __DEVICE_H__
#define __DEVICE_H__
@@ -31,19 +48,27 @@
extern "C" {
#endif
-#include "ra.h"
-#include "resman.h"
+#include "ra.h" /* RA_ARENA */
+#include "resman.h" /* PRESMAN_ITEM */
+/* BM context forward reference */
typedef struct _BM_CONTEXT_ BM_CONTEXT;
+/* pre-defined MMU structure forward references */
typedef struct _MMU_HEAP_ MMU_HEAP;
typedef struct _MMU_CONTEXT_ MMU_CONTEXT;
+/* physical resource types: */
+/* contiguous system memory */
#define PVRSRV_BACKINGSTORE_SYSMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+0))
+/* non-contiguous system memory */
#define PVRSRV_BACKINGSTORE_SYSMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+1))
+/* contiguous local device memory */
#define PVRSRV_BACKINGSTORE_LOCALMEM_CONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+2))
+/* non-contiguous local device memory */
#define PVRSRV_BACKINGSTORE_LOCALMEM_NONCONTIG (1<<(PVRSRV_MEM_BACKINGSTORE_FIELD_SHIFT+3))
+/* heap types: */
typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
#define DEVICE_MEMORY_HEAP_PERCONTEXT 0
#define DEVICE_MEMORY_HEAP_KERNEL 1
@@ -51,38 +76,38 @@ typedef IMG_UINT32 DEVICE_MEMORY_HEAP_TYPE;
#define DEVICE_MEMORY_HEAP_SHARED_EXPORTED 3
#define PVRSRV_DEVICE_NODE_FLAGS_PORT80DISPLAY 1
-#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2
+#define PVRSRV_DEVICE_NODE_FLAGS_MMU_OPT_INV 2 /* FIXME : Optimal Invalidation is not default */
typedef struct _DEVICE_MEMORY_HEAP_INFO_
{
-
+ /* heap identifier */
IMG_UINT32 ui32HeapID;
-
+ /* heap identifier string */
IMG_CHAR *pszName;
-
+ /* backing store identifier string */
IMG_CHAR *pszBSName;
-
+ /* Device virtual address of base of heap */
IMG_DEV_VIRTADDR sDevVAddrBase;
-
+ /* heapsize in bytes */
IMG_UINT32 ui32HeapSize;
-
+ /* Flags, includes physical resource (backing store type). Must be available to SOC */
IMG_UINT32 ui32Attribs;
-
+ /* Heap type: per device, kernel only, shared, shared_exported */
DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
-
+ /* kernel heap handle */
IMG_HANDLE hDevMemHeap;
-
+ /* ptr to local memory allocator for this heap */
RA_ARENA *psLocalDevMemArena;
-
+ /* MMU data page size (4kb, 16kb, 256kb, 1Mb, 4Mb) */
IMG_UINT32 ui32DataPageSize;
IMG_UINT32 ui32XTileStride;
@@ -91,48 +116,56 @@ typedef struct _DEVICE_MEMORY_HEAP_INFO_
typedef struct _DEVICE_MEMORY_INFO_
{
-
+ /* size of address space, as log2 */
IMG_UINT32 ui32AddressSpaceSizeLog2;
-
-
-
+ /*
+ flags, includes physical memory resource types available to the system.
+ Allows for validation at heap creation, define PVRSRV_BACKINGSTORE_XXX
+ */
IMG_UINT32 ui32Flags;
-
+ /* heap count. Doesn't include additional heaps from PVRSRVCreateDeviceMemHeap */
IMG_UINT32 ui32HeapCount;
-
+ /* the sync heap id - common code needs to know */
IMG_UINT32 ui32SyncHeapID;
-
+ /* heap for buffer mappings */
IMG_UINT32 ui32MappingHeapID;
-
+ /* heap for ion buffers */
+ IMG_UINT32 ui32IonHeapID;
+
+ /* device memory heap info about each heap in a device address space */
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeap;
-
+ /* BM kernel context for the device */
BM_CONTEXT *pBMKernelContext;
-
+ /* BM context list for the device*/
BM_CONTEXT *pBMContext;
} DEVICE_MEMORY_INFO;
+/*!
+ ****************************************************************************
+ Device memory descriptor for a given system
+ ****************************************************************************/
typedef struct DEV_ARENA_DESCRIPTOR_TAG
{
- IMG_UINT32 ui32HeapID;
+ IMG_UINT32 ui32HeapID; /*!< memory pool has a unique id for diagnostic purposes */
- IMG_CHAR *pszName;
+ IMG_CHAR *pszName; /*!< memory pool has a unique string for diagnostic purposes */
- IMG_DEV_VIRTADDR BaseDevVAddr;
+ IMG_DEV_VIRTADDR BaseDevVAddr; /*!< Device virtual base address of the managed memory pool. */
- IMG_UINT32 ui32Size;
+ IMG_UINT32 ui32Size; /*!< Size in bytes of the managed memory pool. */
- DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;
+ DEVICE_MEMORY_HEAP_TYPE DevMemHeapType;/*!< heap type */
-
+ /* MMU data page size (4kb, 16kb, 256kb, 1Mb, 4Mb) */
IMG_UINT32 ui32DataPageSize;
DEVICE_MEMORY_HEAP_INFO *psDeviceMemoryHeapInfo;
@@ -140,26 +173,30 @@ typedef struct DEV_ARENA_DESCRIPTOR_TAG
} DEV_ARENA_DESCRIPTOR;
+/*
+ PDUMP MMU atttributes
+*/
typedef struct _PDUMP_MMU_ATTRIB_
{
PVRSRV_DEVICE_IDENTIFIER sDevId;
IMG_CHAR *pszPDRegRegion;
-
+ /* data page info */
IMG_UINT32 ui32DataPageMask;
-
+ /* page table info */
IMG_UINT32 ui32PTEValid;
IMG_UINT32 ui32PTSize;
IMG_UINT32 ui32PTEAlignShift;
-
+ /* page directory info */
IMG_UINT32 ui32PDEMask;
IMG_UINT32 ui32PDEAlignShift;
} PDUMP_MMU_ATTRIB;
+/* forward reference to _SYS_DATA_ */
typedef struct _SYS_DATA_TAG_ *PSYS_DATA;
typedef struct _PVRSRV_DEVICE_NODE_
@@ -167,17 +204,18 @@ typedef struct _PVRSRV_DEVICE_NODE_
PVRSRV_DEVICE_IDENTIFIER sDevId;
IMG_UINT32 ui32RefCount;
-
-
-
+ /*
+ callbacks the device must support:
+ */
+ /* device initialiser */
PVRSRV_ERROR (*pfnInitDevice) (IMG_VOID*);
-
+ /* device deinitialiser */
PVRSRV_ERROR (*pfnDeInitDevice) (IMG_VOID*);
-
+ /* device post-finalise compatibility check */
PVRSRV_ERROR (*pfnInitDeviceCompatCheck) (struct _PVRSRV_DEVICE_NODE_*);
-
+ /* device MMU interface */
PVRSRV_ERROR (*pfnMMUInitialise)(struct _PVRSRV_DEVICE_NODE_*, MMU_CONTEXT**, IMG_DEV_PHYADDR*);
IMG_VOID (*pfnMMUFinalise)(MMU_CONTEXT*);
IMG_VOID (*pfnMMUInsertHeap)(MMU_CONTEXT*, MMU_HEAP*);
@@ -198,6 +236,16 @@ typedef struct _PVRSRV_DEVICE_NODE_
IMG_SIZE_T uSize,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapPagesSparse)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR devVAddr,
+ IMG_SYS_PHYADDR SysPAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
IMG_VOID (*pfnMMUMapShadow)(MMU_HEAP *pMMU,
IMG_DEV_VIRTADDR MapBaseDevVAddr,
IMG_SIZE_T uSize,
@@ -206,6 +254,18 @@ typedef struct _PVRSRV_DEVICE_NODE_
IMG_DEV_VIRTADDR *pDevVAddr,
IMG_UINT32 ui32MemFlags,
IMG_HANDLE hUniqueTag);
+ IMG_VOID (*pfnMMUMapShadowSparse)(MMU_HEAP *pMMU,
+ IMG_DEV_VIRTADDR MapBaseDevVAddr,
+ IMG_UINT32 ui32ChunkSize,
+ IMG_UINT32 ui32NumVirtChunks,
+ IMG_UINT32 ui32NumPhysChunks,
+ IMG_BOOL *pabMapChunk,
+ IMG_CPU_VIRTADDR CpuVAddr,
+ IMG_HANDLE hOSMemHandle,
+ IMG_DEV_VIRTADDR *pDevVAddr,
+ IMG_UINT32 ui32MemFlags,
+ IMG_HANDLE hUniqueTag);
+
IMG_VOID (*pfnMMUUnmapPages)(MMU_HEAP *pMMU,
IMG_DEV_VIRTADDR dev_vaddr,
IMG_UINT32 ui32PageCount,
@@ -225,7 +285,7 @@ typedef struct _PVRSRV_DEVICE_NODE_
IMG_VOID (*pfnMMUGetCacheFlushRange)(MMU_CONTEXT *pMMUContext, IMG_UINT32 *pui32RangeMask);
IMG_VOID (*pfnMMUGetPDPhysAddr)(MMU_CONTEXT *pMMUContext, IMG_DEV_PHYADDR *psDevPAddr);
-
+ /* tiling range control functions */
PVRSRV_ERROR (*pfnAllocMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
PVRSRV_KERNEL_MEM_INFO *psMemInfo,
IMG_UINT32 ui32TilingStride,
@@ -233,36 +293,36 @@ typedef struct _PVRSRV_DEVICE_NODE_
PVRSRV_ERROR (*pfnFreeMemTilingRange)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode,
IMG_UINT32 ui32RangeIndex);
-
+ /* LISR handler for device */
IMG_BOOL (*pfnDeviceISR)(IMG_VOID*);
-
+ /* ISR data */
IMG_VOID *pvISRData;
-
+ /* System/SOC specific interrupt bit relating to this device */
IMG_UINT32 ui32SOCInterruptBit;
-
+ /* MISR handler for device */
IMG_VOID (*pfnDeviceMISR)(IMG_VOID*);
-
+ /* Software command complete callback for device */
IMG_VOID (*pfnDeviceCommandComplete)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
-
+ /* Flag indicating that command complete callback needs to be reprocessed */
IMG_BOOL bReProcessDeviceCommandComplete;
IMG_VOID (*pfnCacheInvalidate)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
-
+ /* information about the device's address space and heaps */
DEVICE_MEMORY_INFO sDevMemoryInfo;
-
+ /* private device information */
IMG_VOID *pvDevice;
- IMG_UINT32 ui32pvDeviceSize;
+ IMG_UINT32 ui32pvDeviceSize; /* required by GetClassDeviceInfo API */
-
+ /* Resource Manager Context */
PRESMAN_CONTEXT hResManContext;
-
+ /* pointer back to parent sysdata */
PSYS_DATA psSysData;
-
+ /* default MMU PT/PD backing store to use for the device */
RA_ARENA *psLocalDevMemArena;
IMG_UINT32 ui32Flags;
@@ -271,9 +331,11 @@ typedef struct _PVRSRV_DEVICE_NODE_
struct _PVRSRV_DEVICE_NODE_ **ppsThis;
#if defined(PDUMP)
-
+ /* device-level callback which is called when pdump.exe starts.
+ * Should be implemented in device-specific init code, e.g. sgxinit.c
+ */
PVRSRV_ERROR (*pfnPDumpInitDevice)(struct _PVRSRV_DEVICE_NODE_ *psDeviceNode);
-
+ /* device-level callback to return pdump ID associated to a memory context */
IMG_UINT32 (*pfnMMUGetContextID)(IMG_HANDLE hDevMemContext);
#endif
} PVRSRV_DEVICE_NODE;
@@ -292,23 +354,45 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVDeinitialiseDevice(IMG_UINT32 ui32DevIndex);
#if !defined(USE_CODE)
-IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
- IMG_UINT32 ui32Value,
- IMG_UINT32 ui32Mask,
- IMG_UINT32 ui32Timeoutus,
- IMG_UINT32 ui32PollPeriodus,
- IMG_BOOL bAllowPreemption);
+/*!
+******************************************************************************
-#endif
+ @Function PollForValueKM
+
+ @Description
+ Polls for a value to match a masked read of sysmem
+
+ @Input pui32LinMemAddr : CPU linear address of the mem to poll
+ @Input ui32Value : req'd value
+ @Input ui32Mask : Mask
+ @Input ui32Timeoutus : maximum total time to wait (us)
+ @Input ui32PollPeriodus : minimum delay between consecutive polls (us)
+ @Input bAllowPreemption : allow the polling loop to be preempted
+
+ @Return PVRSRV_ERROR :
+
+******************************************************************************/
+IMG_IMPORT PVRSRV_ERROR IMG_CALLCONV PollForValueKM(volatile IMG_UINT32* pui32LinMemAddr,
+ IMG_UINT32 ui32Value,
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Timeoutus,
+ IMG_UINT32 ui32PollPeriodus,
+ IMG_BOOL bAllowPreemption);
+
+#endif /* !defined(USE_CODE) */
#if defined (USING_ISR_INTERRUPTS)
PVRSRV_ERROR IMG_CALLCONV PollForInterruptKM(IMG_UINT32 ui32Value,
- IMG_UINT32 ui32Mask,
- IMG_UINT32 ui32Waitus,
- IMG_UINT32 ui32Tries);
-#endif
+ IMG_UINT32 ui32Mask,
+ IMG_UINT32 ui32Waitus,
+ IMG_UINT32 ui32Tries);
+
+#endif /* #if defined (USING_ISR_INTERRUPTS) */
+/* The following functions don't really belong here (srvkm.h might be a better
+ * place), but as they use the device data structures, this is the most convenient
+ * place for them. */
PVRSRV_ERROR IMG_CALLCONV PVRSRVInit(PSYS_DATA psSysData);
IMG_VOID IMG_CALLCONV PVRSRVDeInit(PSYS_DATA psSysData);
IMG_BOOL IMG_CALLCONV PVRSRVDeviceLISR(PVRSRV_DEVICE_NODE *psDeviceNode);
@@ -319,5 +403,8 @@ IMG_VOID IMG_CALLCONV PVRSRVMISR(IMG_VOID *pvSysData);
}
#endif
-#endif
+#endif /* __DEVICE_H__ */
+/******************************************************************************
+ End of file (device.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/handle.h b/sgx/services4/srvkm/include/handle.h
index 536fa56..fdfe0a8 100644
--- a/sgx/services4/srvkm/include/handle.h
+++ b/sgx/services4/srvkm/include/handle.h
@@ -1,31 +1,184 @@
-/**********************************************************************
+/*************************************************************************/ /*!
+@Title Handle Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide handle management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+#ifndef __HANDLE_H__
+#define __HANDLE_H__
+
+/*
+ * Handle API
+ * ----------
+ * The handle API is intended to provide handles for kernel resources,
+ * which can then be passed back to user space processes.
*
- * Copyright (C) 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.
- * 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".
+ * The following functions comprise the API. Each function takes a
+ * pointer to a PVRSRV_HANDLE_BASE strcture, one of which is allocated
+ * for each process, and stored in the per-process data area. Use
+ * KERNEL_HANDLE_BASE for handles not allocated for a particular process,
+ * or for handles that need to be allocated before the PVRSRV_HANDLE_BASE
+ * structure for the process is available.
*
- * Contact Information:
- * Imagination Technologies Ltd. <gpl-support@imgtec.com>
- * Home Park Estate, Kings Langley, Herts, WD4 8LZ, UK
+ * PVRSRV_ERROR PVRSRVAllocHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * PVRSRV_HANDLE_ALLOC_FLAG eFlag);
*
- ******************************************************************************/
-
-#ifndef __HANDLE_H__
-#define __HANDLE_H__
+ * Allocate a handle phHandle, for the resource of type eType pointed to by
+ * pvData.
+ *
+ * For handles that have a definite lifetime, where the corresponding
+ * resource is explicitly created and destroyed, eFlag should be zero.
+ *
+ * If the resource is not explicitly created and destroyed, eFlag should be
+ * set to PVRSRV_HANDLE_ALLOC_FLAG_SHARED. For a given process, the same
+ * handle will be returned each time a handle for the resource is allocated
+ * with the PVRSRV_HANDLE_ALLOC_FLAG_SHARED flag.
+ *
+ * If a particular resource may be referenced multiple times by a
+ * given process, setting eFlag to PVRSRV_HANDLE_ALLOC_FLAG_MULTI
+ * will allow multiple handles to be allocated for the resource.
+ * Such handles cannot be found with PVRSRVFindHandle.
+ *
+ * PVRSRV_ERROR PVRSRVAllocSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType,
+ * PVRSRV_HANDLE_ALLOC_FLAG eFlag, IMG_HANDLE hParent);
+ *
+ * This function is similar to PVRSRVAllocHandle, except that the allocated
+ * handles are associated with a parent handle, hParent, that has been
+ * allocated previously. Subhandles are automatically deallocated when their
+ * parent handle is dealloacted.
+ * Subhandles can be treated as ordinary handles. For example, they may
+ * have subhandles of their own, and may be explicity deallocated using
+ * PVRSRVReleaseHandle (see below).
+ *
+ * PVRSRV_ERROR PVRSRVFindHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE *phHandle, IMG_VOID *pvData, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Find the handle previously allocated for the resource pointed to by
+ * pvData, of type eType. Handles allocated with the flag
+ * PVRSRV_HANDLE_ALLOC_FLAG_MULTI cannot be found using this
+ * function.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Given a handle for a resource of type eType, return the pointer to the
+ * resource.
+ *
+ * PVRSRV_ERROR PVRSRVLookuSubHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType,
+ * IMH_HANDLE hAncestor);
+ *
+ * Similar to PVRSRVLookupHandle, but checks the handle is a descendent
+ * of hAncestor.
+ *
+ * PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle);
+ *
+ * This function returns the resource pointer corresponding to the
+ * given handle, and the resource type in peType. This function is
+ * intended for situations where a handle may be one of several types,
+ * but the type isn't known beforehand.
+ *
+ * PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Deallocate a handle of given type.
+ *
+ * PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * This function combines the functionality of PVRSRVLookupHandle and
+ * PVRSRVReleaseHandle, deallocating the handle after looking it up.
+ *
+ * PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_PVOID *phParent, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
+ *
+ * Return the parent of a handle in *phParent, or IMG_NULL if the handle has
+ * no parent.
+ *
+ * PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_UINT32 ui32BatchSize)
+ *
+ * Allocate a new handle batch. This preallocates ui32BatchSize handles.
+ * Batch mode simplifies the handling of handle allocation failures.
+ * The handle API is unchanged in batch mode, except that handles freed
+ * in batch mode will not be available for reallocation until the batch
+ * is committed or released (see below).
+ *
+ * PVRSRV_ERROR PVRSRVCommitHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+ * void PVRSRVReleaseHandleBatch(PVRSRV_HANDLE_BASE *psBase)
+ *
+ * When handle allocation from a handle batch is complete, the
+ * batch must be committed by calling PVRSRVCommitHandleBatch. If
+ * an error occurred, and none of the handles in the batch are no
+ * longer needed, PVRSRVReleaseHandleBatch must be called.
+ * The macros PVRSRVAllocHandleNR, and PVRSRVAllocSubHandleNR
+ * are defined for use in batch mode. These work the same way
+ * as PVRSRVAllocHandle and PVRSRVAllocSubHandle, except that
+ * they don't return a value, relying on the fact that
+ * PVRSRVCommitHandleBatch will not commit any of the handles
+ * in a batch if there was an error allocating one of the
+ * handles in the batch.
+ *
+ * PVRSRV_ERROR PVRSRVSetMaxHandle(PVRSRV_HANDLE_BASE *psBase,
+ * IMG_UINT32 ui32MaxHandle)
+ * Set the maximum handle number. This is intended to restrict the
+ * handle range so that it will fit within a given field width. For
+ * example, setting the maximum handle number to 0x7fffffff, would
+ * ensure the handles would fit within a 31 bit width field. This
+ * facility should be used with caution, as it restricts the number of
+ * handles that can be allocated.
+ *
+ * IMG_UINT32 PVRSRVGetMaxHandle(PVRSRV_HANDLE_BASE *psBase)
+ * Return the maximum handle number, or 0 if the setting of a limit
+ * is not supported.
+ *
+ * PVRSRV_ERROR PVRSRVEnableHandlePurging(PVRSRV_HANDLE_BASE *psBase)
+ * Allows unused handle space to be reclaimed, by calling
+ * PVRSRVPurgeHandles. Note that allocating handles may have a
+ * higher overhead if purging is enabled.
+ *
+ * PVRSRV_ERROR PVRSRVPurgeHandles((PVRSRV_HANDLE_BASE *psBase)
+ * Purge handles for a handle base that has purging enabled.
+ */
#if defined (__cplusplus)
extern "C" {
@@ -65,13 +218,13 @@ typedef enum
typedef enum
{
-
+ /* No flags */
PVRSRV_HANDLE_ALLOC_FLAG_NONE = 0,
-
+ /* Share a handle that already exists for a given data pointer */
PVRSRV_HANDLE_ALLOC_FLAG_SHARED = 0x01,
-
+ /* Muliple handles can point at the given data pointer */
PVRSRV_HANDLE_ALLOC_FLAG_MULTI = 0x02,
-
+ /* Subhandles are allocated in a private handle space */
PVRSRV_HANDLE_ALLOC_FLAG_PRIVATE = 0x04
} PVRSRV_HANDLE_ALLOC_FLAG;
@@ -119,7 +272,7 @@ PVRSRV_ERROR PVRSRVGetParentHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *phPare
PVRSRV_ERROR PVRSRVLookupAndReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
PVRSRV_ERROR PVRSRVReleaseHandle(PVRSRV_HANDLE_BASE *psBase, IMG_HANDLE hHandle, PVRSRV_HANDLE_TYPE eType);
-#endif
+#endif /* #if defined (SUPPORT_SID_INTERFACE) */
PVRSRV_ERROR PVRSRVNewHandleBatch(PVRSRV_HANDLE_BASE *psBase, IMG_UINT32 ui32BatchSize);
@@ -143,7 +296,7 @@ PVRSRV_ERROR PVRSRVHandleInit(IMG_VOID);
PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID);
-#else
+#else /* #if defined (PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)*/
#define KERNEL_HANDLE_BASE IMG_NULL
@@ -196,7 +349,10 @@ static INLINE
PVRSRV_ERROR PVRSRVLookupHandleAnyType(PVRSRV_HANDLE_BASE *psBase, IMG_PVOID *ppvData, PVRSRV_HANDLE_TYPE *peType, IMG_HANDLE hHandle)
{
PVR_UNREFERENCED_PARAMETER(psBase);
-
+ /*
+ * Unlike the other functions here, the returned results will need
+ * to be handled differently for the secure and non-secure cases.
+ */
*peType = PVRSRV_HANDLE_TYPE_NONE;
*ppvData = hHandle;
@@ -388,8 +544,13 @@ PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
return PVRSRV_OK;
}
-#endif
+#endif /* #if defined (PVR_SECURE_HANDLES) || defined (SUPPORT_SID_INTERFACE)*/
+/*
+ * Versions of PVRSRVAllocHandle and PVRSRVAllocSubHandle with no return
+ * values. Intended for use with batched handle allocation, relying on
+ * CommitHandleBatch to detect handle allocation errors.
+ */
#define PVRSRVAllocHandleNR(psBase, phHandle, pvData, eType, eFlag) \
(IMG_VOID)PVRSRVAllocHandle(psBase, phHandle, pvData, eType, eFlag)
@@ -400,5 +561,8 @@ PVRSRV_ERROR PVRSRVHandleDeInit(IMG_VOID)
}
#endif
-#endif
+#endif /* __HANDLE_H__ */
+/******************************************************************************
+ End of file (handle.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/hash.h b/sgx/services4/srvkm/include/hash.h
index 3662089..2179ac0 100644
--- a/sgx/services4/srvkm/include/hash.h
+++ b/sgx/services4/srvkm/include/hash.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Self scaling hash tables
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Implements simple self scaling hash tables.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _HASH_H_
#define _HASH_H_
@@ -34,6 +51,10 @@
extern "C" {
#endif
+/*
+ * Keys passed to the comparsion function are only guaranteed to
+ * be aligned on an IMG_UINTPTR_T boundary.
+ */
typedef IMG_UINT32 HASH_FUNC(IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
typedef IMG_BOOL HASH_KEY_COMP(IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
@@ -44,31 +65,203 @@ typedef PVRSRV_ERROR (*HASH_pfnCallback) (
IMG_UINTPTR_T v
);
+/*!
+******************************************************************************
+ @Function HASH_Func_Default
+
+ @Description Hash function intended for hashing keys composed of
+ IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey - a pointer to the key to hash.
+ @Input uHashTabLen - the length of the hash table.
+
+ @Return The hash value.
+******************************************************************************/
IMG_UINT32 HASH_Func_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey, IMG_UINT32 uHashTabLen);
+/*!
+******************************************************************************
+ @Function HASH_Key_Comp_Default
+
+ @Description Compares keys composed of IMG_UINTPTR_T arrays.
+
+ @Input uKeySize - the size of the hash key, in bytes.
+ @Input pKey1 - pointer to first hash key to compare.
+ @Input pKey2 - pointer to second hash key to compare.
+
+ @Return IMG_TRUE - the keys match.
+ IMG_FALSE - the keys don't match.
+******************************************************************************/
IMG_BOOL HASH_Key_Comp_Default (IMG_SIZE_T uKeySize, IMG_VOID *pKey1, IMG_VOID *pKey2);
+/*!
+******************************************************************************
+ @Function HASH_Create_Extended
+
+ @Description Create a self scaling hash table, using the supplied
+ key size, and the supllied hash and key comparsion
+ functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the number
+ of entries in the hash table, not its size in
+ bytes.
+ @Input uKeySize - the size of the key, in bytes.
+ @Input pfnHashFunc - pointer to hash function.
+ @Input pfnKeyComp - pointer to key comparsion function.
+
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create_Extended (IMG_UINT32 uInitialLen, IMG_SIZE_T uKeySize, HASH_FUNC *pfnHashFunc, HASH_KEY_COMP *pfnKeyComp);
+/*!
+******************************************************************************
+ @Function HASH_Create
+
+ @Description Create a self scaling hash table with a key
+ consisting of a single IMG_UINTPTR_T, and using
+ the default hash and key comparison functions.
+
+ @Input uInitialLen - initial and minimum length of the
+ hash table, where the length refers to the
+ number of entries in the hash table, not its size
+ in bytes.
+
+ @Return IMG_NULL or hash table handle.
+******************************************************************************/
HASH_TABLE * HASH_Create (IMG_UINT32 uInitialLen);
+/*!
+******************************************************************************
+ @Function HASH_Delete
+
+ @Description Delete a hash table created by HASH_Create_Extended or
+ HASH_Create. All entries in the table must have been
+ removed before calling this function.
+
+ @Input pHash - hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID HASH_Delete (HASH_TABLE *pHash);
+/*!
+******************************************************************************
+ @Function HASH_Insert_Extended
+
+ @Description Insert a key value pair into a hash table created
+ with HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+******************************************************************************/
IMG_BOOL HASH_Insert_Extended (HASH_TABLE *pHash, IMG_VOID *pKey, IMG_UINTPTR_T v);
+/*!
+******************************************************************************
+ @Function HASH_Insert
+
+ @Description Insert a key value pair into a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table.
+ @Input k - the key value.
+ @Input v - the value associated with the key.
+
+ @Return IMG_TRUE - success.
+ IMG_FALSE - failure.
+******************************************************************************/
IMG_BOOL HASH_Insert (HASH_TABLE *pHash, IMG_UINTPTR_T k, IMG_UINTPTR_T v);
+/*!
+******************************************************************************
+ @Function HASH_Remove_Extended
+
+ @Description Remove a key from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to key.
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Remove_Extended(HASH_TABLE *pHash, IMG_VOID *pKey);
+/*!
+******************************************************************************
+ @Function HASH_Remove
+
+ @Description Remove a key value pair from a hash table created
+ with HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+
+ @Return 0 if the key is missing, or the value associated
+ with the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Remove (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+/*!
+******************************************************************************
+ @Function HASH_Retrieve_Extended
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create_Extended.
+
+ @Input pHash - the hash table.
+ @Input pKey - pointer to the key.
+
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Retrieve_Extended (HASH_TABLE *pHash, IMG_VOID *pKey);
+/*!
+******************************************************************************
+ @Function HASH_Retrieve
+
+ @Description Retrieve a value from a hash table created with
+ HASH_Create.
+
+ @Input pHash - the hash table
+ @Input k - the key
+
+ @Return 0 if the key is missing, or the value associated with
+ the key.
+******************************************************************************/
IMG_UINTPTR_T HASH_Retrieve (HASH_TABLE *pHash, IMG_UINTPTR_T k);
+/*!
+******************************************************************************
+ @Function HASH_Interate
+
+ @Description Iterate over every entry in the hash table
+
+ @Input pHash - the old hash table
+ @Input HASH_pfnCallback - the size of the old hash table
+
+ @Return Callback error if any, otherwise PVRSRV_OK
+******************************************************************************/
PVRSRV_ERROR HASH_Iterate(HASH_TABLE *pHash, HASH_pfnCallback pfnCallback);
#ifdef HASH_TRACE
+/*!
+******************************************************************************
+ @Function HASH_Dump
+
+ @Description Dump out some information about a hash table.
+
+ @Input pHash - the hash table
+
+ @Return None
+******************************************************************************/
IMG_VOID HASH_Dump (HASH_TABLE *pHash);
#endif
@@ -76,5 +269,10 @@ IMG_VOID HASH_Dump (HASH_TABLE *pHash);
}
#endif
-#endif
+#endif /* _HASH_H_ */
+
+/******************************************************************************
+ End of file (hash.h)
+******************************************************************************/
+
diff --git a/sgx/services4/srvkm/include/lists.h b/sgx/services4/srvkm/include/lists.h
index a02307a..f39c8e2 100644
--- a/sgx/services4/srvkm/include/lists.h
+++ b/sgx/services4/srvkm/include/lists.h
@@ -1,35 +1,91 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Linked list shared functions templates.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Definition of the linked list function templates.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __LISTS_UTILS__
#define __LISTS_UTILS__
+/* instruct QAC to ignore warnings about the following custom formatted macros */
+/* PRQA S 0881,3410 ++ */
#include <stdarg.h>
#include "img_types.h"
+/*
+ - USAGE -
+
+ The list functions work with any structure that provides the fields psNext and
+ ppsThis. In order to make a function available for a given type, it is required
+ to use the funcion template macro that creates the actual code.
+
+ There are 4 main types of functions:
+ - INSERT : given a pointer to the head pointer of the list and a pointer to
+ the node, inserts it as the new head.
+ - REMOVE : given a pointer to a node, removes it from its list.
+ - FOR EACH : apply a function over all the elements of a list.
+ - ANY : apply a function over the elements of a list, until one of them
+ return a non null value, and then returns it.
+
+ The two last functions can have a variable argument form, with allows to pass
+ additional parameters to the callback function. In order to do this, the
+ callback function must take two arguments, the first is the current node and
+ the second is a list of variable arguments (va_list).
+
+ The ANY functions have also another for wich specifies the return type of the
+ callback function and the default value returned by the callback function.
+
+*/
+
+/*!
+******************************************************************************
+ @Function List_##TYPE##_ForEach
+
+ @Description Apply a callback function to all the elements of a list.
+
+ @Input psHead - the head of the list to be processed.
+ @Input pfnCallBack - the function to be applied to each element
+ of the list.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_FOR_EACH(TYPE) \
IMG_VOID List_##TYPE##_ForEach(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psNode))
@@ -61,6 +117,19 @@ IMG_VOID List_##TYPE##_ForEach_va(TYPE *psHead, IMG_VOID(*pfnCallBack)(TYPE* psN
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Any
+
+ @Description Applies a callback function to the elements of a list until
+ the function returns a non null value, then returns it.
+
+ @Input psHead - the head of the list to be processed.
+ @Input pfnCallBack - the function to be applied to each element
+ of the list.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_ANY(TYPE) \
IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode))
@@ -81,6 +150,8 @@ IMG_VOID* List_##TYPE##_Any(TYPE *psHead, IMG_VOID* (*pfnCallBack)(TYPE* psNode)
}
+/*with variable arguments, that will be passed as a va_list to the callback function*/
+
#define DECLARE_LIST_ANY_VA(TYPE) \
IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNode, va_list va), ...)
@@ -101,6 +172,8 @@ IMG_VOID* List_##TYPE##_Any_va(TYPE *psHead, IMG_VOID*(*pfnCallBack)(TYPE* psNod
return pResult;\
}
+/*those ones are for extra type safety, so there's no need to use castings for the results*/
+
#define DECLARE_LIST_ANY_2(TYPE, RTYPE, CONTINUE) \
RTYPE List_##TYPE##_##RTYPE##_Any(TYPE *psHead, RTYPE (*pfnCallBack)(TYPE* psNode))
@@ -142,6 +215,16 @@ RTYPE List_##TYPE##_##RTYPE##_Any_va(TYPE *psHead, RTYPE(*pfnCallBack)(TYPE* psN
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Remove
+
+ @Description Removes a given node from the list.
+
+ @Input psNode - the pointer to the node to be removed.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_REMOVE(TYPE) \
IMG_VOID List_##TYPE##_Remove(TYPE *psNode)
@@ -155,6 +238,17 @@ IMG_VOID List_##TYPE##_Remove(TYPE *psNode)\
}\
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Insert
+
+ @Description Inserts a given node at the beginnning of the list.
+
+ @Input psHead - The pointer to the pointer to the head node.
+ @Input psNode - The pointer to the node to be inserted.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_INSERT(TYPE) \
IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)
@@ -170,6 +264,16 @@ IMG_VOID List_##TYPE##_Insert(TYPE **ppsHead, TYPE *psNewNode)\
}\
}
+/*!
+******************************************************************************
+ @Function List_##TYPE##_Reverse
+
+ @Description Reverse a list in place
+
+ @Input ppsHead - The pointer to the pointer to the head node.
+
+ @Return None
+******************************************************************************/
#define DECLARE_LIST_REVERSE(TYPE) \
IMG_VOID List_##TYPE##_Reverse(TYPE **ppsHead)
@@ -242,3 +346,5 @@ IMG_VOID* MatchPowerDeviceIndex_AnyVaCb(PVRSRV_POWER_DEV *psPowerDev, va_list va
#endif
+/* re-enable warnings */
+/* PRQA S 0881,3410 -- */
diff --git a/sgx/services4/srvkm/include/metrics.h b/sgx/services4/srvkm/include/metrics.h
index 69e1b3d..3326a7f 100644
--- a/sgx/services4/srvkm/include/metrics.h
+++ b/sgx/services4/srvkm/include/metrics.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Time measurement interface.
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _METRICS_
#define _METRICS_
@@ -90,21 +106,21 @@ extern IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID);
#if defined(__sh__)
-#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM))
+#define TST_REG ((volatile IMG_UINT8 *) (psDevInfo->pvSOCRegsBaseKM)) // timer start register
-#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28))
-#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32))
-#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36))
+#define TCOR_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+28)) // timer constant register_2
+#define TCNT_2 ((volatile IMG_UINT *) (psDevInfo->pvSOCRegsBaseKM+32)) // timer counter register_2
+#define TCR_2 ((volatile IMG_UINT16 *)(psDevInfo->pvSOCRegsBaseKM+36)) // timer control register_2
#define TIMER_DIVISOR 4
-#endif
+#endif /* defined(__sh__) */
-#else
+#else /* defined(DEBUG) || defined(TIMING) */
@@ -119,12 +135,15 @@ extern IMG_VOID PVRSRVOutputMetricTotals(IMG_VOID);
-#endif
+#endif /* defined(DEBUG) || defined(TIMING) */
#if defined(__cplusplus)
}
#endif
-#endif
+#endif /* _METRICS_ */
+/**************************************************************************
+ End of file (metrics.h)
+**************************************************************************/
diff --git a/sgx/services4/srvkm/include/osfunc.h b/sgx/services4/srvkm/include/osfunc.h
index 2341c87..953a4b3 100644
--- a/sgx/services4/srvkm/include/osfunc.h
+++ b/sgx/services4/srvkm/include/osfunc.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title OS functions header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS specific API definitions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifdef DEBUG_RELEASE_BUILD
#pragma optimize( "", off )
#define DEBUG 1
@@ -46,9 +62,13 @@ extern "C" {
#endif
-
+/* setup conditional pageable / non-pageable select */
+ /* Non-Vista OSs only need pageable */
#define PVRSRV_PAGEABLE_SELECT PVRSRV_OS_PAGEABLE_HEAP
+/******************************************************************************
+ * Static defines
+ *****************************************************************************/
#define KERNEL_ID 0xffffffffL
#define POWER_MANAGER_ID 0xfffffffeL
#define ISR_ID 0xfffffffdL
@@ -59,9 +79,12 @@ extern "C" {
#define HOST_PAGEMASK (HOST_PAGESIZE()-1)
#define HOST_PAGEALIGN(addr) (((addr) + HOST_PAGEMASK) & ~HOST_PAGEMASK)
-#define PVRSRV_OS_HEAP_MASK 0xf
-#define PVRSRV_OS_PAGEABLE_HEAP 0x1
-#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2
+/******************************************************************************
+ * Host memory heaps
+ *****************************************************************************/
+#define PVRSRV_OS_HEAP_MASK 0xf /* host heap flags mask */
+#define PVRSRV_OS_PAGEABLE_HEAP 0x1 /* allocation pageable */
+#define PVRSRV_OS_NON_PAGEABLE_HEAP 0x2 /* allocation non pageable */
IMG_UINT32 OSClockus(IMG_VOID);
@@ -80,26 +103,36 @@ IMG_VOID OSMemCopy(IMG_VOID *pvDst, IMG_VOID *pvSrc, IMG_SIZE_T ui32Size);
IMG_VOID *OSMapPhysToLin(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE *phOSMemHandle);
IMG_BOOL OSUnMapPhysToLin(IMG_VOID *pvLinAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
-PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
+PVRSRV_ERROR OSReservePhys(IMG_CPU_PHYADDR BasePAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hBMHandle, IMG_VOID **ppvCpuVAddr, IMG_HANDLE *phOSMemHandle);
PVRSRV_ERROR OSUnReservePhys(IMG_VOID *pvCpuVAddr, IMG_SIZE_T ui32Bytes, IMG_UINT32 ui32Flags, IMG_HANDLE hOSMemHandle);
-#if defined(__linux__) && defined(__KERNEL__)
+/* Some terminology:
+ *
+ * FLUSH Flush w/ invalidate
+ * CLEAN Flush w/o invalidate
+ * INVALIDATE Invalidate w/o flush
+ */
+
+#if (defined(__linux__) && defined(__KERNEL__)) || (UNDER_CE >= 600)
IMG_VOID OSFlushCPUCacheKM(IMG_VOID);
IMG_VOID OSCleanCPUCacheKM(IMG_VOID);
IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length);
IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length);
IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length);
-#else
+#else /* defined(__linux__) && defined(__KERNEL__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSFlushCPUCacheKM)
@@ -115,10 +148,12 @@ static INLINE IMG_VOID OSCleanCPUCacheKM(IMG_VOID) {}
#pragma inline(OSFlushCPUCacheRangeKM)
#endif
static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
PVR_UNREFERENCED_PARAMETER(ui32Length);
return IMG_FALSE;
@@ -128,10 +163,12 @@ static INLINE IMG_BOOL OSFlushCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
#pragma inline(OSCleanCPUCacheRangeKM)
#endif
static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
PVR_UNREFERENCED_PARAMETER(ui32Length);
return IMG_FALSE;
@@ -141,16 +178,18 @@ static INLINE IMG_BOOL OSCleanCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
#pragma inline(OSInvalidateCPUCacheRangeKM)
#endif
static INLINE IMG_BOOL OSInvalidateCPUCacheRangeKM(IMG_HANDLE hOSMemHandle,
+ IMG_UINT32 ui32ByteOffset,
IMG_VOID *pvRangeAddrStart,
IMG_UINT32 ui32Length)
{
PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ PVR_UNREFERENCED_PARAMETER(ui32ByteOffset);
PVR_UNREFERENCED_PARAMETER(pvRangeAddrStart);
PVR_UNREFERENCED_PARAMETER(ui32Length);
return IMG_FALSE;
}
-#endif
+#endif /* defined(__linux__) && defined(__KERNEL__) */
#if (defined(__linux__) || defined(__QNXNTO__))
PVRSRV_ERROR OSRegisterDiscontigMem(IMG_SYS_PHYADDR *pBasePAddr,
@@ -162,7 +201,7 @@ PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
IMG_SIZE_T ui32Bytes,
IMG_UINT32 ui32Flags,
IMG_HANDLE hOSMemHandle);
-#else
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSRegisterDiscontigMem)
#endif
@@ -196,7 +235,7 @@ static INLINE PVRSRV_ERROR OSUnRegisterDiscontigMem(IMG_VOID *pvCpuVAddr,
return PVRSRV_ERROR_NOT_SUPPORTED;
}
-#endif
+#endif /* defined(__linux__) */
#if (defined(__linux__) || defined(__QNXNTO__))
@@ -211,8 +250,16 @@ static INLINE PVRSRV_ERROR OSReserveDiscontigPhys(IMG_SYS_PHYADDR *pBasePAddr, I
#else
extern IMG_CPU_PHYADDR SysSysPAddrToCpuPAddr(IMG_SYS_PHYADDR SysPAddr);
-
- return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, ppvCpuVAddr, phOSMemHandle);
+ /*
+ * On uITRON we know:
+ * 1. We will only be called with a non-contig physical if we
+ * already have a contiguous CPU linear
+ * 2. There is a one->one mapping of CpuPAddr -> CpuVAddr
+ * 3. Looking up the first CpuPAddr will find the first CpuVAddr
+ * 4. We don't need to unmap
+ */
+
+ return OSReservePhys(SysSysPAddrToCpuPAddr(pBasePAddr[0]), ui32Bytes, ui32Flags, IMG_NULL, ppvCpuVAddr, phOSMemHandle);
#endif
}
@@ -221,10 +268,10 @@ static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SI
#if defined(__linux__) || defined(__QNXNTO__)
OSUnRegisterDiscontigMem(pvCpuVAddr, ui32Bytes, ui32Flags, hOSMemHandle);
#endif
-
+ /* We don't need to unmap */
return PVRSRV_OK;
}
-#else
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
@@ -253,7 +300,7 @@ static INLINE PVRSRV_ERROR OSUnReserveDiscontigPhys(IMG_VOID *pvCpuVAddr, IMG_SI
return PVRSRV_ERROR_NOT_SUPPORTED;
}
-#endif
+#endif /* defined(__linux__) */
PVRSRV_ERROR OSRegisterMem(IMG_CPU_PHYADDR BasePAddr,
IMG_VOID *pvCpuVAddr,
@@ -304,18 +351,33 @@ IMG_UINT32 OSGetCurrentProcessIDKM(IMG_VOID);
IMG_UINTPTR_T OSGetCurrentThreadID( IMG_VOID );
IMG_VOID OSMemSet(IMG_VOID *pvDest, IMG_UINT8 ui8Value, IMG_SIZE_T ui32Size);
-PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
+PVRSRV_ERROR OSAllocPages_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_UINT32 ui32PageSize,
+ IMG_PVOID pvPrivData, IMG_UINT32 ui32PrivDataLength, IMG_HANDLE hBMHandle, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phPageAlloc);
PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hPageAlloc);
+/*---------------------
+The set of macros below follows this pattern:
+
+f(x) = if F -> f2(g(x))
+ else -> g(x)
+
+g(x) = if G -> g2(h(x))
+ else -> h(x)
+
+h(x) = ...
+
+-----------------------*/
+
+/*If level 3 wrapper is enabled, we add a PVR_TRACE and call the next level, else just call the next level*/
#ifdef PVRSRV_LOG_MEMORY_ALLOCS
#define OSAllocMem(flags, size, linAddr, blockAlloc, logStr) \
(PVR_TRACE(("OSAllocMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): " logStr " (size = 0x%lx)", size)), \
OSAllocMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__))
- #define OSAllocPages(flags, size, pageSize, linAddr, pageAlloc) \
+ #define OSAllocPages(flags, size, pageSize, privdata, privdatalength, bmhandle, linAddr, pageAlloc) \
(PVR_TRACE(("OSAllocPages(" #flags ", " #size ", " #pageSize ", " #linAddr ", " #pageAlloc "): (size = 0x%lx)", size)), \
- OSAllocPages_Impl(flags, size, pageSize, linAddr, pageAlloc))
+ OSAllocPages_Impl(flags, size, pageSize, linAddr, privdata, privdatalength, bmhandle, pageAlloc))
#define OSFreeMem(flags, size, linAddr, blockAlloc) \
(PVR_TRACE(("OSFreeMem(" #flags ", " #size ", " #linAddr ", " #blockAlloc "): (pointer = 0x%X)", linAddr)), \
@@ -330,6 +392,8 @@ PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pv
OSFreeMem_Debug_Wrapper(flags, size, linAddr, blockAlloc, __FILE__, __LINE__)
#endif
+/*If level 2 wrapper is enabled declare the function,
+else alias to level 1 wrapper, else the wrapper function will be used*/
#ifdef PVRSRV_DEBUG_OS_MEMORY
PVRSRV_ERROR OSAllocMem_Debug_Wrapper(IMG_UINT32 ui32Flags,
@@ -360,14 +424,16 @@ PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pv
} eValid;
} OSMEM_DEBUG_INFO;
- #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
- #define TEST_BUFFER_PADDING_AFTER (8)
+ #define TEST_BUFFER_PADDING_STATUS (sizeof(OSMEM_DEBUG_INFO))
+ #define TEST_BUFFER_PADDING_AFTER (8)
#define TEST_BUFFER_PADDING (TEST_BUFFER_PADDING_STATUS + TEST_BUFFER_PADDING_AFTER)
#else
#define OSAllocMem_Debug_Wrapper OSAllocMem_Debug_Linux_Memory_Allocations
#define OSFreeMem_Debug_Wrapper OSFreeMem_Debug_Linux_Memory_Allocations
#endif
+/*If level 1 wrapper is enabled declare the functions with extra parameters
+else alias to level 0 and declare the functions without the extra debugging parameters*/
#if (defined(__linux__) || defined(__QNXNTO__)) && defined(DEBUG_LINUX_MEMORY_ALLOCATIONS)
PVRSRV_ERROR OSAllocMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID *ppvLinAddr, IMG_HANDLE *phBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
PVRSRV_ERROR OSFreeMem_Impl(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pvLinAddr, IMG_HANDLE hBlockAlloc, IMG_CHAR *pszFilename, IMG_UINT32 ui32Line);
@@ -384,8 +450,6 @@ PVRSRV_ERROR OSFreePages(IMG_UINT32 ui32Flags, IMG_SIZE_T ui32Size, IMG_PVOID pv
OSFreeMem_Impl(flags, size, addr, blockAlloc)
#endif
-IMG_VOID OSMemHandleRegisterSmart(IMG_VOID *hOSMemHandle, IMG_HANDLE hSmartCache);
-IMG_VOID OSMemHandleUnegisterSmart(IMG_VOID *hOSMemHandle, IMG_HANDLE hSmartCache);
#if defined(SUPPORT_DRI_DRM_EXTERNAL)
IMG_VOID OSMemHandleSetGEM(IMG_VOID *hOSMemHandle, IMG_HANDLE buf);
@@ -407,6 +471,20 @@ static INLINE IMG_CPU_PHYADDR OSMemHandleToCpuPAddr(IMG_HANDLE hOSMemHandle, IMG
return sCpuPAddr;
}
#endif
+
+#if defined(__linux__)
+IMG_BOOL OSMemHandleIsPhysContig(IMG_VOID *hOSMemHandle);
+#else
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSMemHandleIsPhysContig)
+#endif
+static INLINE IMG_BOOL OSMemHandleIsPhysContig(IMG_HANDLE hOSMemHandle)
+{
+ PVR_UNREFERENCED_PARAMETER(hOSMemHandle);
+ return IMG_FALSE;
+}
+#endif
+
PVRSRV_ERROR OSInitEnvData(IMG_PVOID *ppvEnvSpecificData);
PVRSRV_ERROR OSDeInitEnvData(IMG_PVOID pvEnvSpecificData);
IMG_CHAR* OSStringCopy(IMG_CHAR *pszDest, const IMG_CHAR *pszSrc);
@@ -433,7 +511,7 @@ PVRSRV_ERROR OSEventObjectOpenKM(PVRSRV_EVENTOBJECT *psEventObject,
IMG_HANDLE *phOSEvent);
PVRSRV_ERROR OSEventObjectCloseKM(PVRSRV_EVENTOBJECT *psEventObject,
IMG_HANDLE hOSEventKM);
-#endif
+#endif /* #if defined (SUPPORT_SID_INTERFACE) */
PVRSRV_ERROR OSBaseAllocContigMemory(IMG_SIZE_T ui32Size, IMG_CPU_VIRTADDR *pLinAddr, IMG_CPU_PHYADDR *pPhysAddr);
@@ -468,15 +546,57 @@ IMG_VOID OSBreakResourceLock(PVRSRV_RESOURCE *psResource, IMG_UINT32 ui32ID);
#define OSPowerLockWrap SysPowerLockWrap
#define OSPowerLockUnwrap SysPowerLockUnwrap
#else
+/******************************************************************************
+ @Function OSPowerLockWrap
+
+ @Description OS-specific wrapper around the power lock
+
+ @Input bTryLock - don't block on lock contention
+
+ @Return PVRSRV_ERROR
+******************************************************************************/
PVRSRV_ERROR OSPowerLockWrap(IMG_BOOL bTryLock);
+/******************************************************************************
+ @Function OSPowerLockUnwrap
+
+ @Description OS-specific wrapper around the power unlock
+
+ @Return IMG_VOID
+******************************************************************************/
IMG_VOID OSPowerLockUnwrap(IMG_VOID);
-#endif
+#endif /* SYS_CUSTOM_POWERLOCK_WRAP */
+
+/*!
+******************************************************************************
+ @Function OSWaitus
+ @Description
+ This function implements a busy wait of the specified microseconds
+ This function does NOT release thread quanta
+
+ @Input ui32Timeus - (us)
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSWaitus(IMG_UINT32 ui32Timeus);
+/*!
+******************************************************************************
+
+ @Function OSSleepms
+
+ @Description
+ This function implements a sleep of the specified milliseconds
+ This function may allow pre-emption if implemented
+ @Input ui32Timems - (ms)
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSSleepms(IMG_UINT32 ui32Timems);
IMG_HANDLE OSFuncHighResTimerCreate(IMG_VOID);
@@ -486,6 +606,14 @@ IMG_VOID OSReleaseThreadQuanta(IMG_VOID);
IMG_UINT32 OSPCIReadDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg);
IMG_VOID OSPCIWriteDword(IMG_UINT32 ui32Bus, IMG_UINT32 ui32Dev, IMG_UINT32 ui32Func, IMG_UINT32 ui32Reg, IMG_UINT32 ui32Value);
+IMG_IMPORT
+IMG_UINT32 ReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
+
+IMG_IMPORT
+IMG_VOID WriteHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset, IMG_UINT32 ui32Value);
+
+IMG_IMPORT IMG_VOID WriteHWRegs(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Count, PVRSRV_HWREG *psHWRegs);
+
#ifndef OSReadHWReg
IMG_UINT32 OSReadHWReg(IMG_PVOID pvLinRegBaseAddr, IMG_UINT32 ui32Offset);
#endif
@@ -525,6 +653,17 @@ PVRSRV_ERROR OSPCIResumeDev(PVRSRV_PCI_DEV_HANDLE hPVRPCI);
PVRSRV_ERROR OSScheduleMISR(IMG_VOID *pvSysData);
+/******************************************************************************
+
+ @Function OSPanic
+
+ @Description Take action in response to an unrecoverable driver error
+
+ @Input IMG_VOID
+
+ @Return IMG_VOID
+
+******************************************************************************/
IMG_VOID OSPanic(IMG_VOID);
IMG_BOOL OSProcHasPrivSrvInit(IMG_VOID);
@@ -591,7 +730,7 @@ static inline IMG_VOID OSMemoryBarrier(IMG_VOID)
mb();
}
-#else
+#else /* defined(__linux__) && defined(__KERNEL__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSWriteMemoryBarrier)
@@ -603,11 +742,58 @@ static INLINE IMG_VOID OSWriteMemoryBarrier(IMG_VOID) { }
#endif
static INLINE IMG_VOID OSMemoryBarrier(IMG_VOID) { }
-#endif
+#endif /* defined(__linux__) && defined(__KERNEL__) */
+
+/* Atomic functions */
+PVRSRV_ERROR OSAtomicAlloc(IMG_PVOID *ppvRefCount);
+IMG_VOID OSAtomicFree(IMG_PVOID pvRefCount);
+IMG_VOID OSAtomicInc(IMG_PVOID pvRefCount);
+IMG_BOOL OSAtomicDecAndTest(IMG_PVOID pvRefCount);
+IMG_UINT32 OSAtomicRead(IMG_PVOID pvRefCount);
+
+PVRSRV_ERROR OSTimeCreateWithUSOffset(IMG_PVOID *pvRet, IMG_UINT32 ui32MSOffset);
+IMG_BOOL OSTimeHasTimePassed(IMG_PVOID pvData);
+IMG_VOID OSTimeDestroy(IMG_PVOID pvData);
+
+#if defined(__linux__)
+IMG_VOID OSReleaseBridgeLock(IMG_VOID);
+IMG_VOID OSReacquireBridgeLock(IMG_VOID);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReleaseBridgeLock)
+#endif
+static INLINE IMG_VOID OSReleaseBridgeLock(IMG_VOID) { }
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSReacquireBridgeLock)
+#endif
+static INLINE IMG_VOID OSReacquireBridgeLock(IMG_VOID) { }
+
+#endif
+
+#if defined(__linux__)
+IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size);
+#else
+
+#ifdef INLINE_IS_PRAGMA
+#pragma inline(OSGetCurrentProcessNameKM)
+#endif
+static INLINE IMG_VOID OSGetCurrentProcessNameKM(IMG_CHAR *pszName, IMG_UINT32 ui32Size)
+{
+ PVR_UNREFERENCED_PARAMETER(pszName);
+ PVR_UNREFERENCED_PARAMETER(ui32Size);
+}
+
+#endif
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __OSFUNC_H__ */
+
+/******************************************************************************
+ End of file (osfunc.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/osperproc.h b/sgx/services4/srvkm/include/osperproc.h
index e5c81da..9c72be0 100644
--- a/sgx/services4/srvkm/include/osperproc.h
+++ b/sgx/services4/srvkm/include/osperproc.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OS specific per process data interface
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description OS specific per process data interface
+@License Dual MIT/GPLv2
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __OSPERPROC_H__
#define __OSPERPROC_H__
@@ -36,7 +52,7 @@ PVRSRV_ERROR OSPerProcessPrivateDataInit(IMG_HANDLE *phOsPrivateData);
PVRSRV_ERROR OSPerProcessPrivateDataDeInit(IMG_HANDLE hOsPrivateData);
PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHandleBase);
-#else
+#else /* defined(__linux__) */
#ifdef INLINE_IS_PRAGMA
#pragma inline(OSPerProcessPrivateDataInit)
#endif
@@ -66,11 +82,14 @@ static INLINE PVRSRV_ERROR OSPerProcessSetHandleOptions(PVRSRV_HANDLE_BASE *psHa
return PVRSRV_OK;
}
-#endif
+#endif /* defined(__linux__) */
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __OSPERPROC_H__ */
+/******************************************************************************
+ End of file (osperproc.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/pdump_int.h b/sgx/services4/srvkm/include/pdump_int.h
index 9f68549..9777f63 100644
--- a/sgx/services4/srvkm/include/pdump_int.h
+++ b/sgx/services4/srvkm/include/pdump_int.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Parameter dump internal common functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
#ifndef __PDUMP_INT_H__
#define __PDUMP_INT_H__
@@ -31,22 +48,35 @@
extern "C" {
#endif
+/*
+ * This file contains internal pdump utility functions which may be accessed
+ * from OS-specific code. The header should not be included outside of srvkm
+ * pdump files.
+ */
+
#if !defined(_UITRON)
+/*
+ * No dbgdriver on uitron, so ignore any common functions for communicating
+ * with dbgdriver.
+ */
#include "dbgdrvif.h"
+/* Callbacks which are registered with the debug driver. */
IMG_EXPORT IMG_VOID PDumpConnectionNotify(IMG_VOID);
-#endif
+#endif /* !defined(_UITRON) */
typedef enum
{
-
+ /* Continuous writes are always captured in the dbgdrv; the buffer will
+ * expand if no client/sink process is running.
+ */
PDUMP_WRITE_MODE_CONTINUOUS = 0,
-
+ /* Last frame capture */
PDUMP_WRITE_MODE_LASTFRAME,
-
+ /* Capture frame, binary data */
PDUMP_WRITE_MODE_BINCM,
-
+ /* Persistent capture, append data to init phase */
PDUMP_WRITE_MODE_PERSISTENT
} PDUMP_DDWMODE;
@@ -63,5 +93,9 @@ IMG_UINT32 PDumpOSDebugDriverWrite( PDBG_STREAM psStream,
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* __PDUMP_INT_H__ */
+
+/******************************************************************************
+ End of file (pdump_int.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/pdump_km.h b/sgx/services4/srvkm/include/pdump_km.h
index 418c6d7..97b5e2a 100644
--- a/sgx/services4/srvkm/include/pdump_km.h
+++ b/sgx/services4/srvkm/include/pdump_km.h
@@ -1,50 +1,76 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title pdump functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for pdump functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _PDUMP_KM_H_
#define _PDUMP_KM_H_
+/*
+ * Include the OS abstraction APIs
+ */
#include "pdump_osfunc.h"
#if defined(__cplusplus)
extern "C" {
#endif
+/*
+ * Pull in pdump flags from services include
+ */
#include "pdump.h"
#define PDUMP_PD_UNIQUETAG (IMG_HANDLE)0
#define PDUMP_PT_UNIQUETAG (IMG_HANDLE)0
+/*
+ * PDump streams (common to all OSes)
+ */
#define PDUMP_STREAM_PARAM2 0
#define PDUMP_STREAM_SCRIPT2 1
#define PDUMP_STREAM_DRIVERINFO 2
#define PDUMP_NUM_STREAMS 3
#if defined(PDUMP_DEBUG_OUTFILES)
+/* counter increments each time debug write is called */
extern IMG_UINT32 g_ui32EveryLineCounter;
#endif
@@ -114,8 +140,6 @@ extern IMG_UINT32 g_ui32EveryLineCounter;
PVRSRV_ERROR PDumpStopInitPhaseKM(IMG_VOID);
IMG_IMPORT PVRSRV_ERROR PDumpSetFrameKM(IMG_UINT32 ui32Frame);
IMG_IMPORT PVRSRV_ERROR PDumpCommentKM(IMG_CHAR *pszComment, IMG_UINT32 ui32Flags);
-
-
IMG_IMPORT PVRSRV_ERROR PDumpDriverInfoKM(IMG_CHAR *pszString, IMG_UINT32 ui32Flags);
PVRSRV_ERROR PDumpRegWithFlagsKM(IMG_CHAR *pszPDumpRegName,
@@ -258,7 +282,8 @@ extern IMG_UINT32 g_ui32EveryLineCounter;
IMG_UINT32 ui32NumBytes,
IMG_UINT32 ui32PageSize,
IMG_HANDLE hUniqueTag,
- IMG_BOOL bInterleaved);
+ IMG_BOOL bInterleaved,
+ IMG_BOOL bSparse);
PVRSRV_ERROR PDumpFreePageTable(PVRSRV_DEVICE_IDENTIFIER *psDevID,
IMG_HANDLE hOSMemHandle,
IMG_CPU_VIRTADDR pvLinAddr,
@@ -309,7 +334,7 @@ extern IMG_UINT32 g_ui32EveryLineCounter;
IMG_VOID PDumpSuspendKM(IMG_VOID);
IMG_VOID PDumpResumeKM(IMG_VOID);
-
+ /* New pdump common functions */
PVRSRV_ERROR PDumpStoreMemToFile(PDUMP_MMU_ATTRIB *psMMUAttrib,
IMG_CHAR *pszFileName,
IMG_UINT32 ui32FileOffset,
@@ -356,7 +381,7 @@ extern IMG_UINT32 g_ui32EveryLineCounter;
#define PDUMPRESUME PDumpResumeKM
#else
- #if (((defined(LINUX) || defined(__QNXNTO__)) || defined(GCC_IA32)) || defined(GCC_ARM))
+#if (((defined(LINUX) || defined(__QNXNTO__)) || defined(GCC_IA32)) || defined(GCC_ARM))
#define PDUMPMEMPOL(args...)
#define PDUMPMEM(args...)
#define PDUMPMEMPTENTRIES(args...)
@@ -410,5 +435,8 @@ extern IMG_UINT32 g_ui32EveryLineCounter;
}
#endif
-#endif
+#endif /* _PDUMP_KM_H_ */
+/******************************************************************************
+ End of file (pdump_km.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/pdump_osfunc.h b/sgx/services4/srvkm/include/pdump_osfunc.h
index f3ed914..3bda7df 100644
--- a/sgx/services4/srvkm/include/pdump_osfunc.h
+++ b/sgx/services4/srvkm/include/pdump_osfunc.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title OS-independent interface to helper functions for pdump
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include <stdarg.h>
@@ -31,12 +47,23 @@ extern "C" {
#endif
+/*
+ * Some OSes (WinXP,CE) allocate the string on the stack, but some
+ * (Linux,Symbian) use a global variable/lock instead.
+ * Would be good to use the same across all OSes.
+ *
+ * A handle is returned which represents IMG_CHAR* type on all OSes except
+ * Symbian when it represents PDumpState* type.
+ *
+ * The allocated buffer length is also returned on OSes where it's
+ * supported (e.g. Linux).
+ */
#define MAX_PDUMP_STRING_LENGTH (256)
-
-
-
+ /*
+ * Linux
+ */
#define PDUMP_GET_SCRIPT_STRING() \
IMG_HANDLE hScript; \
IMG_UINT32 ui32MaxLen; \
@@ -69,17 +96,42 @@ extern "C" {
eError = PDumpOSGetFilenameString(&pszFileName, &ui32MaxLenFileName);\
if(eError != PVRSRV_OK) return eError;
-
+ /*!
+ * @name PDumpOSGetScriptString
+ * @brief Get the "script" buffer
+ * @param phScript - buffer handle for pdump script
+ * @param pui32MaxLen - max length of the script buffer
+ * FIXME: the max length should be internal to the OS-specific code
+ * @return error (always PVRSRV_OK on some OSes)
+ */
PVRSRV_ERROR PDumpOSGetScriptString(IMG_HANDLE *phScript, IMG_UINT32 *pui32MaxLen);
-
+ /*!
+ * @name PDumpOSGetMessageString
+ * @brief Get the "message" buffer
+ * @param pszMsg - buffer pointer for pdump messages
+ * @param pui32MaxLen - max length of the message buffer
+ * FIXME: the max length should be internal to the OS-specific code
+ * @return error (always PVRSRV_OK on some OSes)
+ */
PVRSRV_ERROR PDumpOSGetMessageString(IMG_CHAR **ppszMsg, IMG_UINT32 *pui32MaxLen);
-
+ /*!
+ * @name PDumpOSGetFilenameString
+ * @brief Get the "filename" buffer
+ * @param ppszFile - buffer pointer for filename
+ * @param pui32MaxLen - max length of the filename buffer
+ * FIXME: the max length should be internal to the OS-specific code
+ * @return error (always PVRSRV_OK on some OSes)
+ */
PVRSRV_ERROR PDumpOSGetFilenameString(IMG_CHAR **ppszFile, IMG_UINT32 *pui32MaxLen);
+/*
+ * Define macro for processing variable args list in OS-independent
+ * manner. See e.g. PDumpComment().
+ */
#define PDUMP_va_list va_list
#define PDUMP_va_start va_start
@@ -87,37 +139,138 @@ extern "C" {
+/*!
+ * @name PDumpOSGetStream
+ * @brief Get a handle to the labelled stream (cast the handle to PDBG_STREAM to use it)
+ * @param ePDumpStream - stream label
+ */
IMG_HANDLE PDumpOSGetStream(IMG_UINT32 ePDumpStream);
+/*!
+ * @name PDumpOSGetStreamOffset
+ * @brief Return current offset within the labelled stream
+ * @param ePDumpStream - stream label
+ */
IMG_UINT32 PDumpOSGetStreamOffset(IMG_UINT32 ePDumpStream);
+/*!
+ * @name PDumpOSGetParamFileNum
+ * @brief Return file number of the 'script' stream, in the case that the file was split
+ * @param ePDumpStream - stream label
+ */
IMG_UINT32 PDumpOSGetParamFileNum(IMG_VOID);
+/*!
+ * @name PDumpOSCheckForSplitting
+ * @brief Check if the requested pdump params are too large for a single file
+ * @param hStream - pdump stream
+ * @param ui32Size - size of params to dump (bytes)
+ * @param ui32Flags - pdump flags
+ */
IMG_VOID PDumpOSCheckForSplitting(IMG_HANDLE hStream, IMG_UINT32 ui32Size, IMG_UINT32 ui32Flags);
+/*!
+ * @name PDumpOSIsSuspended
+ * @brief Is the pdump stream busy?
+ * @return IMG_BOOL
+ */
IMG_BOOL PDumpOSIsSuspended(IMG_VOID);
+/*!
+ * @name PDumpOSIsSuspended
+ * @brief Is the pdump jump table initialised?
+ * @return IMG_BOOL
+ */
IMG_BOOL PDumpOSJTInitialised(IMG_VOID);
+/*!
+ * @name PDumpOSWriteString
+ * @brief General function for writing to pdump stream.
+ * Usually more convenient to use PDumpOSWriteString2 below.
+ * @param hDbgStream - pdump stream handle
+ * @param psui8Data - data to write
+ * @param ui32Size - size of write
+ * @param ui32Flags - pdump flags
+ * @return error
+ */
IMG_BOOL PDumpOSWriteString(IMG_HANDLE hDbgStream,
IMG_UINT8 *psui8Data,
IMG_UINT32 ui32Size,
IMG_UINT32 ui32Flags);
+/*!
+ * @name PDumpOSWriteString2
+ * @brief Write a string to the "script" output stream
+ * @param pszScript - buffer to write (ptr to state structure on Symbian)
+ * @param ui32Flags - pdump flags
+ * @return error
+ */
IMG_BOOL PDumpOSWriteString2(IMG_HANDLE hScript, IMG_UINT32 ui32Flags);
+/*!
+ * @name PDumpOSBufprintf
+ * @brief Printf to OS-specific pdump state buffer
+ * @param hBuf - buffer handle to write into (ptr to state structure on Symbian)
+ * @param ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param pszFormat - format string
+ */
PVRSRV_ERROR PDumpOSBufprintf(IMG_HANDLE hBuf, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+/*!
+ * @name PDumpOSDebugPrintf
+ * @brief Debug message during pdumping
+ * @param pszFormat - format string
+ */
IMG_VOID PDumpOSDebugPrintf(IMG_CHAR* pszFormat, ...) IMG_FORMAT_PRINTF(1, 2);
+/*
+ * FIXME: Is this function useful for Symbian?
+ * Write into a IMG_CHAR* on all OSes. Can be allocated on the stack or heap.
+ */
+/*!
+ * @name PDumpOSSprintf
+ * @brief Printf to IMG char array
+ * @param pszComment - char array to print into
+ * @param pszFormat - format string
+ */
PVRSRV_ERROR PDumpOSSprintf(IMG_CHAR *pszComment, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR *pszFormat, ...) IMG_FORMAT_PRINTF(3, 4);
+/*!
+ * @name PDumpOSVSprintf
+ * @brief Printf to IMG string using variable args (see stdarg.h). This is necessary
+ * because the ... notation does not support nested function calls.
+ * @param pszMsg - char array to print into
+ * @param ui32ScriptSizeMax - maximum size of data to write (not supported on all OSes)
+ * @param pszFormat - format string
+ * @param vaArgs - variable args structure (from stdarg.h)
+ */
PVRSRV_ERROR PDumpOSVSprintf(IMG_CHAR *pszMsg, IMG_UINT32 ui32ScriptSizeMax, IMG_CHAR* pszFormat, PDUMP_va_list vaArgs) IMG_FORMAT_PRINTF(3, 0);
+/*!
+ * @name PDumpOSBuflen
+ * @param hBuffer - handle to buffer (ptr to state structure on Symbian)
+ * @param ui32BuffeRSizeMax - max size of buffer (chars)
+ * @return length of buffer, will always be <= ui32BufferSizeMax
+ */
IMG_UINT32 PDumpOSBuflen(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+/*!
+ * @name PDumpOSVerifyLineEnding
+ * @brief Put \r\n sequence at the end if it isn't already there
+ * @param hBuffer - handle to buffer
+ * @param ui32BufferSizeMax - max size of buffer (chars)
+ */
IMG_VOID PDumpOSVerifyLineEnding(IMG_HANDLE hBuffer, IMG_UINT32 ui32BufferSizeMax);
+/*!
+ * @name PDumpOSCPUVAddrToDevPAddr
+ * @brief OS function to convert CPU virtual to device physical for dumping pages
+ * @param hOSMemHandle mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param ui32Offset dword offset into allocation (for use with mem handle, e.g. linux)
+ * @param pui8LinAddr CPU linear addr (usually a kernel virtual address)
+ * @param ui32PageSize page size, used for assertion check
+ * @return psDevPAddr device physical addr
+ */
IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
@@ -125,16 +278,37 @@ IMG_VOID PDumpOSCPUVAddrToDevPAddr(PVRSRV_DEVICE_TYPE eDeviceType,
IMG_UINT32 ui32PageSize,
IMG_DEV_PHYADDR *psDevPAddr);
+/*!
+ * @name PDumpOSCPUVAddrToPhysPages
+ * @brief OS function to convert CPU virtual to backing physical pages
+ * @param hOSMemHandle mem allocation handle (used if kernel virtual mem space is limited, e.g. linux)
+ * @param ui32Offset offset within mem allocation block
+ * @param pui8LinAddr CPU linear addr
+ * @param ui32DataPageMask mask for data page (= data page size -1)
+ * @return pui32PageOffset CPU page offset (same as device page offset if page sizes equal)
+ */
IMG_VOID PDumpOSCPUVAddrToPhysPages(IMG_HANDLE hOSMemHandle,
IMG_UINT32 ui32Offset,
IMG_PUINT8 pui8LinAddr,
IMG_UINT32 ui32DataPageMask,
IMG_UINT32 *pui32PageOffset);
+/*!
+ * @name PDumpOSReleaseExecution
+ * @brief OS function to switch to another process, to clear pdump buffers
+ */
IMG_VOID PDumpOSReleaseExecution(IMG_VOID);
+/*!
+ * @name PDumpOSIsCaptureFrameKM
+ * @brief Is the current frame a capture frame?
+ */
IMG_BOOL PDumpOSIsCaptureFrameKM(IMG_VOID);
+/*!
+ * @name PDumpOSSetFrameKM
+ * @brief Set frame counter
+ */
PVRSRV_ERROR PDumpOSSetFrameKM(IMG_UINT32 ui32Frame);
#if defined (__cplusplus)
diff --git a/sgx/services4/srvkm/include/perfkm.h b/sgx/services4/srvkm/include/perfkm.h
new file mode 100644
index 0000000..719b61d
--- /dev/null
+++ b/sgx/services4/srvkm/include/perfkm.h
@@ -0,0 +1,59 @@
+/*************************************************************************/ /*!
+@Title Vista-specific Perf initialisation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+#ifndef _PERFKM_H_
+#define _PERFKM_H_
+
+#include "img_types.h"
+
+/*
+ * Note, WDDM needs to perform initialisation and deinitialisation
+ * in order to support HW performance measurement. Other platforms
+ * should not need to do anything in these functions.
+ */
+#define PERFINIT()
+#define PERFDEINIT()
+
+#endif /* _PERFKM_H_ */
+
+/******************************************************************************
+ End of file (perfkm.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/perproc.h b/sgx/services4/srvkm/include/perproc.h
index 842680c..d7a7a11 100644
--- a/sgx/services4/srvkm/include/perproc.h
+++ b/sgx/services4/srvkm/include/perproc.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Handle Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Perprocess data
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __PERPROC_H__
#define __PERPROC_H__
@@ -48,27 +64,33 @@ typedef struct _PVRSRV_PER_PROCESS_DATA_
#endif
PVRSRV_HANDLE_BASE *psHandleBase;
#if defined (SUPPORT_SID_INTERFACE)
-
+ /* Handles are being allocated in batches */
IMG_BOOL bHandlesBatched;
#else
#if defined (PVR_SECURE_HANDLES)
-
+ /* Handles are being allocated in batches */
IMG_BOOL bHandlesBatched;
-#endif
-#endif
+#endif /* PVR_SECURE_HANDLES */
+#endif /* SUPPORT_SID_INTERFACE */
IMG_UINT32 ui32RefCount;
-
+ /* True if the process is the initialisation server. */
IMG_BOOL bInitProcess;
#if defined(PDUMP)
-
+ /* True if pdump data from the process is 'persistent' */
IMG_BOOL bPDumpPersistent;
#if defined(SUPPORT_PDUMP_MULTI_PROCESS)
-
+ /* True if this process is marked for pdumping. This flag is
+ * significant in a multi-app environment.
+ */
IMG_BOOL bPDumpActive;
-#endif
+#endif /* SUPPORT_PDUMP_MULTI_PROCESS */
#endif
-
+ /*
+ * OS specific data can be stored via this handle.
+ * See osperproc.h for a generic mechanism for initialising
+ * this field.
+ */
IMG_HANDLE hOsPrivateData;
} PVRSRV_PER_PROCESS_DATA;
@@ -122,5 +144,8 @@ IMG_HANDLE PVRSRVFindPerProcessPrivateData(IMG_VOID)
}
#endif
-#endif
+#endif /* __PERPROC_H__ */
+/******************************************************************************
+ End of file (perproc.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/power.h b/sgx/services4/srvkm/include/power.h
index 9e3dcc4..eb05e2c 100644
--- a/sgx/services4/srvkm/include/power.h
+++ b/sgx/services4/srvkm/include/power.h
@@ -1,29 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Power Management Functions
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Main APIs for power management functions
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef POWER_H
#define POWER_H
@@ -32,6 +48,10 @@ extern "C" {
#endif
+/*!
+ *****************************************************************************
+ * Power management
+ *****************************************************************************/
typedef struct _PVRSRV_POWER_DEV_TAG_
{
@@ -75,9 +95,7 @@ IMG_VOID PVRSRVPowerUnlock(IMG_UINT32 ui32CallerID);
IMG_IMPORT
PVRSRV_ERROR PVRSRVSetDevicePowerStateKM(IMG_UINT32 ui32DeviceIndex,
- PVRSRV_DEV_POWER_STATE eNewPowerState,
- IMG_UINT32 ui32CallerID,
- IMG_BOOL bRetainMutex);
+ PVRSRV_DEV_POWER_STATE eNewPowerState);
IMG_IMPORT
PVRSRV_ERROR PVRSRVSystemPrePowerStateKM(PVRSRV_SYS_POWER_STATE eNewPowerState);
@@ -116,5 +134,8 @@ IMG_VOID PVRSRVDevicePostClockSpeedChange(IMG_UINT32 ui32DeviceIndex,
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* POWER_H */
+/******************************************************************************
+ End of file (power.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/queue.h b/sgx/services4/srvkm/include/queue.h
index ab89527..266cc81 100644
--- a/sgx/services4/srvkm/include/queue.h
+++ b/sgx/services4/srvkm/include/queue.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Command Queue API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Internal structures and definitions for command queues
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef QUEUE_H
#define QUEUE_H
@@ -32,19 +49,33 @@
extern "C" {
#endif
+/*!
+ * Macro to Read Offset in given command queue
+ */
#define UPDATE_QUEUE_ROFF(psQueue, ui32Size) \
(psQueue)->ui32ReadOffset = ((psQueue)->ui32ReadOffset + (ui32Size)) \
& ((psQueue)->ui32QueueSize - 1);
+/*!
+ generic cmd complete structure.
+ This structure represents the storage required between starting and finishing
+ a given cmd and is required to hold the generic sync object update data.
+ note: for any given system we know what command types we support and
+ therefore how much storage is required for any number of commands in progress
+ */
typedef struct _COMMAND_COMPLETE_DATA_
{
IMG_BOOL bInUse;
-
- IMG_UINT32 ui32DstSyncCount;
- IMG_UINT32 ui32SrcSyncCount;
- PVRSRV_SYNC_OBJECT *psDstSync;
- PVRSRV_SYNC_OBJECT *psSrcSync;
- IMG_UINT32 ui32AllocSize;
+ /* <arg(s) to PVRSRVProcessQueues>; */ /*!< TBD */
+ IMG_UINT32 ui32DstSyncCount; /*!< number of dst sync objects */
+ IMG_UINT32 ui32SrcSyncCount; /*!< number of src sync objects */
+ PVRSRV_SYNC_OBJECT *psDstSync; /*!< dst sync ptr list,
+ allocated on back of this structure */
+ PVRSRV_SYNC_OBJECT *psSrcSync; /*!< src sync ptr list,
+ allocated on back of this structure */
+ IMG_UINT32 ui32AllocSize; /*!< allocated size*/
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete; /*!< Command complete callback */
+ IMG_HANDLE hCallbackData; /*!< Command complete callback data */
}COMMAND_COMPLETE_DATA, *PCOMMAND_COMPLETE_DATA;
#if !defined(USE_CODE)
@@ -76,7 +107,9 @@ PVRSRV_ERROR IMG_CALLCONV PVRSRVInsertCommandKM(PVRSRV_QUEUE_INFO *psQueue,
PVRSRV_KERNEL_SYNC_INFO *apsDstSync[],
IMG_UINT32 ui32SrcSyncCount,
PVRSRV_KERNEL_SYNC_INFO *apsSrcSync[],
- IMG_SIZE_T ui32DataByteSize );
+ IMG_SIZE_T ui32DataByteSize,
+ PFN_QUEUE_COMMAND_COMPLETE pfnCommandComplete,
+ IMG_HANDLE hCallbackData);
IMG_IMPORT
PVRSRV_ERROR IMG_CALLCONV PVRSRVGetQueueSpaceKM(PVRSRV_QUEUE_INFO *psQueue,
@@ -99,12 +132,15 @@ IMG_IMPORT
PVRSRV_ERROR PVRSRVRemoveCmdProcListKM(IMG_UINT32 ui32DevIndex,
IMG_UINT32 ui32CmdCount);
-#endif
+#endif /* !defined(USE_CODE) */
#if defined (__cplusplus)
}
#endif
-#endif
+#endif /* QUEUE_H */
+/******************************************************************************
+ End of file (queue.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/ra.h b/sgx/services4/srvkm/include/ra.h
index db141f6..b6bd587 100644
--- a/sgx/services4/srvkm/include/ra.h
+++ b/sgx/services4/srvkm/include/ra.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Allocator API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef _RA_H_
#define _RA_H_
@@ -31,41 +47,46 @@
#include "hash.h"
#include "osfunc.h"
-typedef struct _RA_ARENA_ RA_ARENA;
+/** Resource arena.
+ * struct _RA_ARENA_ deliberately opaque
+ */
+typedef struct _RA_ARENA_ RA_ARENA; //PRQA S 3313
typedef struct _BM_MAPPING_ BM_MAPPING;
+/** Enable support for arena statistics. */
#define RA_STATS
+/** Resource arena statistics. */
struct _RA_STATISTICS_
{
-
+ /** total number of segments add to the arena */
IMG_SIZE_T uSpanCount;
-
+ /** number of current live segments within the arena */
IMG_SIZE_T uLiveSegmentCount;
-
+ /** number of current free segments within the arena */
IMG_SIZE_T uFreeSegmentCount;
-
+ /** total number of resource within the arena */
IMG_SIZE_T uTotalResourceCount;
-
+ /** number of free resource within the arena */
IMG_SIZE_T uFreeResourceCount;
-
+ /** total number of resources allocated from the arena */
IMG_SIZE_T uCumulativeAllocs;
-
+ /** total number of resources returned to the arena */
IMG_SIZE_T uCumulativeFrees;
-
+ /** total number of spans allocated by the callback mechanism */
IMG_SIZE_T uImportCount;
-
+ /** total number of spans deallocated by the callback mechanism */
IMG_SIZE_T uExportCount;
};
typedef struct _RA_STATISTICS_ RA_STATISTICS;
@@ -78,6 +99,23 @@ struct _RA_SEGMENT_DETAILS_
};
typedef struct _RA_SEGMENT_DETAILS_ RA_SEGMENT_DETAILS;
+/**
+ * @Function RA_Create
+ *
+ * @Description
+ *
+ * To create a resource arena.
+ *
+ * @Input name - the name of the arena for diagnostic purposes.
+ * @Input base - the base of an initial resource span or 0.
+ * @Input uSize - the size of an initial resource span or 0.
+ * @Input pRef - the reference to return for the initial resource or 0.
+ * @Input uQuantum - the arena allocation quantum.
+ * @Input alloc - a resource allocation callback or 0.
+ * @Input free - a resource de-allocation callback or 0.
+ * @Input import_handle - handle passed to alloc and free or 0.
+ * @Return arena handle, or IMG_NULL.
+ */
RA_ARENA *
RA_Create (IMG_CHAR *name,
IMG_UINTPTR_T base,
@@ -89,6 +127,8 @@ RA_Create (IMG_CHAR *name,
IMG_SIZE_T *pActualSize,
BM_MAPPING **ppsMapping,
IMG_UINT32 uFlags,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase),
IMG_VOID (*imp_free) (IMG_VOID *,
IMG_UINTPTR_T,
@@ -99,15 +139,73 @@ RA_Create (IMG_CHAR *name,
IMG_HANDLE),
IMG_VOID *import_handle);
+/**
+ * @Function RA_Delete
+ *
+ * @Description
+ *
+ * To delete a resource arena. All resources allocated from the arena
+ * must be freed before deleting the arena.
+ *
+ * @Input pArena - the arena to delete.
+ * @Return None
+ */
IMG_VOID
RA_Delete (RA_ARENA *pArena);
+/**
+ * @Function RA_TestDelete
+ *
+ * @Description
+ *
+ * To test whether it is safe to delete a resource arena. If any allocations
+ * have not been freed, the RA must not be deleted.
+ *
+ * @Input pArena - the arena to test.
+ * @Return IMG_BOOL - IMG_TRUE if is safe to go on and call RA_Delete.
+ */
IMG_BOOL
RA_TestDelete (RA_ARENA *pArena);
+/**
+ * @Function RA_Add
+ *
+ * @Description
+ *
+ * To add a resource span to an arena. The span must not overlap with
+ * any span previously added to the arena.
+ *
+ * @Input pArena - the arena to add a span into.
+ * @Input base - the base of the span.
+ * @Input uSize - the extent of the span.
+ * @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
IMG_BOOL
RA_Add (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_SIZE_T uSize);
+/**
+ * @Function RA_Alloc
+ *
+ * @Description
+ *
+ * To allocate resource from an arena.
+ *
+ * @Input pArena - the arena
+ * @Input uRequestSize - the size of resource segment requested.
+ * @Output pActualSize - the actual_size of resource segment allocated,
+ * typcially rounded up by quantum.
+ * @Output ppsMapping - the user reference associated with allocated
+ * resource span.
+ * @Input uFlags - flags influencing allocation policy.
+ * @Input uAlignment - the alignment constraint required for the
+ * allocated segment, use 0 if alignment not required.
+ * @Input uAlignmentOffset - the required alignment offset
+ * @Input pvPrivData - private data passed to OS allocator
+ * @Input ui32PrivData - length of private data
+ *
+ * @Output pBase - allocated base resource
+ * @Return IMG_TRUE - success, IMG_FALSE - failure
+ */
IMG_BOOL
RA_Alloc (RA_ARENA *pArena,
IMG_SIZE_T uSize,
@@ -116,8 +214,21 @@ RA_Alloc (RA_ARENA *pArena,
IMG_UINT32 uFlags,
IMG_UINT32 uAlignment,
IMG_UINT32 uAlignmentOffset,
+ IMG_PVOID pvPrivData,
+ IMG_UINT32 ui32PrivDataLength,
IMG_UINTPTR_T *pBase);
+/**
+ * @Function RA_Free
+ *
+ * @Description To free a resource segment.
+ *
+ * @Input pArena - the arena the segment was originally allocated from.
+ * @Input base - the base of the resource span to free.
+ * @Input bFreeBackingStore - Should backing store memory be freed?
+ *
+ * @Return None
+ */
IMG_VOID
RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
@@ -142,9 +253,30 @@ RA_Free (RA_ARENA *pArena, IMG_UINTPTR_T base, IMG_BOOL bFreeBackingStore);
}
+/**
+ * @Function RA_GetNextLiveSegment
+ *
+ * @Description Returns details of the next live resource segments
+ *
+ * @Input pArena - the arena the segment was originally allocated from.
+ * @Output psSegDetails - rtn details of segments
+ *
+ * @Return IMG_TRUE if operation succeeded
+ */
IMG_BOOL RA_GetNextLiveSegment(IMG_HANDLE hArena, RA_SEGMENT_DETAILS *psSegDetails);
+/**
+ * @Function RA_GetStats
+ *
+ * @Description gets stats on a given arena
+ *
+ * @Input pArena - the arena the segment was originally allocated from.
+ * @Input ppszStr - string to write stats to
+ * @Input pui32StrLen - length of string
+ *
+ * @Return PVRSRV_ERROR
+ */
PVRSRV_ERROR RA_GetStats(RA_ARENA *pArena,
IMG_CHAR **ppszStr,
IMG_UINT32 *pui32StrLen);
@@ -153,7 +285,7 @@ PVRSRV_ERROR RA_GetStatsFreeMem(RA_ARENA *pArena,
IMG_CHAR **ppszStr,
IMG_UINT32 *pui32StrLen);
-#endif
+#endif /* #ifdef RA_STATS */
#endif
diff --git a/sgx/services4/srvkm/include/refcount.h b/sgx/services4/srvkm/include/refcount.h
new file mode 100644
index 0000000..73f6780
--- /dev/null
+++ b/sgx/services4/srvkm/include/refcount.h
@@ -0,0 +1,204 @@
+/*************************************************************************/ /*!
+@Title Services reference count debugging
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
+#ifndef __REFCOUNT_H__
+#define __REFCOUNT_H__
+
+#include "pvr_bridge_km.h"
+
+#if defined(PVRSRV_REFCOUNT_DEBUG)
+
+void PVRSRVDumpRefCountCCB(void);
+
+#define PVRSRVKernelSyncInfoIncRef(x...) \
+ PVRSRVKernelSyncInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelSyncInfoDecRef(x...) \
+ PVRSRVKernelSyncInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoIncRef(x...) \
+ PVRSRVKernelMemInfoIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVKernelMemInfoDecRef(x...) \
+ PVRSRVKernelMemInfoDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncRef(x...) \
+ PVRSRVBMBufIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecRef(x...) \
+ PVRSRVBMBufDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufIncExport(x...) \
+ PVRSRVBMBufIncExport2(__FILE__, __LINE__, x)
+#define PVRSRVBMBufDecExport(x...) \
+ PVRSRVBMBufDecExport2(__FILE__, __LINE__, x)
+
+void PVRSRVKernelSyncInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelSyncInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVKernelMemInfoDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo);
+void PVRSRVBMBufIncRef2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecRef2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufIncExport2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMBufDecExport2(const IMG_CHAR *pszFile,
+ IMG_INT iLine, BM_BUF *pBuf);
+void PVRSRVBMXProcIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ IMG_UINT32 ui32Index);
+void PVRSRVBMXProcDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ IMG_UINT32 ui32Index);
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+#define PVRSRVOffsetStructIncRef(x...) \
+ PVRSRVOffsetStructIncRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecRef(x...) \
+ PVRSRVOffsetStructDecRef2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructIncMapped(x...) \
+ PVRSRVOffsetStructIncMapped2(__FILE__, __LINE__, x)
+#define PVRSRVOffsetStructDecMapped(x...) \
+ PVRSRVOffsetStructDecMapped2(__FILE__, __LINE__, x)
+
+void PVRSRVOffsetStructIncRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecRef2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructIncMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+void PVRSRVOffsetStructDecMapped2(const IMG_CHAR *pszFile, IMG_INT iLine,
+ PKV_OFFSET_STRUCT psOffsetStruct);
+
+#endif /* defined(__linux__) */
+
+#else /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+static INLINE void PVRSRVDumpRefCountCCB(void) { }
+
+static INLINE void PVRSRVKernelSyncInfoIncRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+ PVRSRVAcquireSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelSyncInfoDecRef(PVRSRV_KERNEL_SYNC_INFO *psKernelSyncInfo,
+ PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ PVR_UNREFERENCED_PARAMETER(psKernelMemInfo);
+ PVRSRVReleaseSyncInfoKM(psKernelSyncInfo);
+}
+
+static INLINE void PVRSRVKernelMemInfoIncRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->ui32RefCount++;
+}
+
+static INLINE void PVRSRVKernelMemInfoDecRef(PVRSRV_KERNEL_MEM_INFO *psKernelMemInfo)
+{
+ psKernelMemInfo->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncRef(BM_BUF *pBuf)
+{
+ pBuf->ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMBufDecRef(BM_BUF *pBuf)
+{
+ pBuf->ui32RefCount--;
+}
+
+static INLINE void PVRSRVBMBufIncExport(BM_BUF *pBuf)
+{
+ pBuf->ui32ExportCount++;
+}
+
+static INLINE void PVRSRVBMBufDecExport(BM_BUF *pBuf)
+{
+ pBuf->ui32ExportCount--;
+}
+
+static INLINE void PVRSRVBMXProcIncRef(IMG_UINT32 ui32Index)
+{
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount++;
+}
+
+static INLINE void PVRSRVBMXProcDecRef(IMG_UINT32 ui32Index)
+{
+ gXProcWorkaroundShareData[ui32Index].ui32RefCount--;
+}
+
+#if defined(__linux__)
+
+/* mmap refcounting is Linux specific */
+#include "mmap.h"
+
+static INLINE void PVRSRVOffsetStructIncRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32RefCount++;
+}
+
+static INLINE void PVRSRVOffsetStructDecRef(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32RefCount--;
+}
+
+static INLINE void PVRSRVOffsetStructIncMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32Mapped++;
+}
+
+static INLINE void PVRSRVOffsetStructDecMapped(PKV_OFFSET_STRUCT psOffsetStruct)
+{
+ psOffsetStruct->ui32Mapped--;
+}
+
+#endif /* defined(__linux__) */
+
+#endif /* defined(PVRSRV_REFCOUNT_DEBUG) */
+
+#endif /* __REFCOUNT_H__ */
diff --git a/sgx/services4/srvkm/include/resman.h b/sgx/services4/srvkm/include/resman.h
index 648e490..6c9b93e 100644
--- a/sgx/services4/srvkm/include/resman.h
+++ b/sgx/services4/srvkm/include/resman.h
@@ -1,28 +1,45 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Resource Manager API
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Provide resource management
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __RESMAN_H__
#define __RESMAN_H__
@@ -31,56 +48,70 @@
extern "C" {
#endif
-enum {
-
- RESMAN_TYPE_SHARED_PB_DESC = 1,
- RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
- RESMAN_TYPE_HW_RENDER_CONTEXT,
- RESMAN_TYPE_HW_TRANSFER_CONTEXT,
- RESMAN_TYPE_HW_2D_CONTEXT,
- RESMAN_TYPE_TRANSFER_CONTEXT,
-
-
- RESMAN_TYPE_DMA_CLIENT_FIFO_DATA,
-
-
-
-
-
- RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF,
- RESMAN_TYPE_DISPLAYCLASS_DEVICE,
+/******************************************************************************
+ * resman definitions
+ *****************************************************************************/
+enum {
+ /* SGX: */
+ RESMAN_TYPE_SHARED_PB_DESC = 1, /*!< Parameter buffer kernel stubs */
+ RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, /*!< Shared parameter buffer creation lock */
+ RESMAN_TYPE_HW_RENDER_CONTEXT, /*!< Hardware Render Context Resource */
+ RESMAN_TYPE_HW_TRANSFER_CONTEXT, /*!< Hardware transfer Context Resource */
+ RESMAN_TYPE_HW_2D_CONTEXT, /*!< Hardware 2D Context Resource */
+ RESMAN_TYPE_TRANSFER_CONTEXT, /*!< Transfer Queue context */
+
+ /* VGX: */
+ RESMAN_TYPE_DMA_CLIENT_FIFO_DATA, /*!< VGX DMA Client FIFO data */
+
+ /* DISPLAY CLASS: */
+ RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, /*!< Display Class Swapchain Reference Resource */
+ RESMAN_TYPE_DISPLAYCLASS_DEVICE, /*!< Display Class Device Resource */
+
+ /* BUFFER CLASS: */
+ RESMAN_TYPE_BUFFERCLASS_DEVICE, /*!< Buffer Class Device Resource */
- RESMAN_TYPE_BUFFERCLASS_DEVICE,
-
-
- RESMAN_TYPE_OS_USERMODE_MAPPING,
-
-
- RESMAN_TYPE_DEVICEMEM_CONTEXT,
- RESMAN_TYPE_DEVICECLASSMEM_MAPPING,
- RESMAN_TYPE_DEVICEMEM_MAPPING,
- RESMAN_TYPE_DEVICEMEM_WRAP,
- RESMAN_TYPE_DEVICEMEM_ALLOCATION,
- RESMAN_TYPE_EVENT_OBJECT,
- RESMAN_TYPE_SHARED_MEM_INFO,
- RESMAN_TYPE_MODIFY_SYNC_OPS,
- RESMAN_TYPE_SYNC_INFO,
+ /* OS specific User mode Mappings: */
+ RESMAN_TYPE_OS_USERMODE_MAPPING, /*!< OS specific User mode mappings */
+ /* COMMON: */
+ RESMAN_TYPE_DEVICEMEM_CONTEXT, /*!< Device Memory Context Resource */
+ RESMAN_TYPE_DEVICECLASSMEM_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_MAPPING, /*!< Device Memory Mapping Resource */
+ RESMAN_TYPE_DEVICEMEM_WRAP, /*!< Device Memory Wrap Resource */
+ RESMAN_TYPE_DEVICEMEM_ALLOCATION, /*!< Device Memory Allocation Resource */
+ RESMAN_TYPE_DEVICEMEM_ION, /*!< Device Memory Ion Resource */
+ RESMAN_TYPE_EVENT_OBJECT, /*!< Event Object */
+ RESMAN_TYPE_SHARED_MEM_INFO, /*!< Shared system memory meminfo */
+ RESMAN_TYPE_MODIFY_SYNC_OPS, /*!< Syncobject synchronisation Resource*/
+ RESMAN_TYPE_SYNC_INFO, /*!< Syncobject Resource*/
- RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION
+ /* KERNEL: */
+ RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION /*!< Device Memory Allocation Resource */
};
-#define RESMAN_CRITERIA_ALL 0x00000000
-#define RESMAN_CRITERIA_RESTYPE 0x00000001
-#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002
-#define RESMAN_CRITERIA_UI32_PARAM 0x00000004
+#define RESMAN_CRITERIA_ALL 0x00000000 /*!< match by criteria all */
+#define RESMAN_CRITERIA_RESTYPE 0x00000001 /*!< match by criteria type */
+#define RESMAN_CRITERIA_PVOID_PARAM 0x00000002 /*!< match by criteria param1 */
+#define RESMAN_CRITERIA_UI32_PARAM 0x00000004 /*!< match by criteria param2 */
typedef PVRSRV_ERROR (*RESMAN_FREE_FN)(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bForceCleanup);
typedef struct _RESMAN_ITEM_ *PRESMAN_ITEM;
typedef struct _RESMAN_CONTEXT_ *PRESMAN_CONTEXT;
+/******************************************************************************
+ * resman functions
+ *****************************************************************************/
+
+/*
+ Note:
+ Resource cleanup can fail with retry in which case we don't remove
+ it from resman's list and either UM or KM will try to release the
+ resource at a later date (and will keep trying until a non-retry
+ error is returned)
+*/
+
PVRSRV_ERROR ResManInit(IMG_VOID);
IMG_VOID ResManDeInit(IMG_VOID);
@@ -114,5 +145,9 @@ IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT hResManContext,
}
#endif
-#endif
+#endif /* __RESMAN_H__ */
+
+/******************************************************************************
+ End of file (resman.h)
+******************************************************************************/
diff --git a/sgx/services4/srvkm/include/services_headers.h b/sgx/services4/srvkm/include/services_headers.h
index 2b5f197..30a4b23 100644
--- a/sgx/services4/srvkm/include/services_headers.h
+++ b/sgx/services4/srvkm/include/services_headers.h
@@ -1,28 +1,47 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Command queues and synchronisation
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Internal structures and definitions for command queues and
+ synchronisation
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
+
#ifndef SERVICES_HEADERS_H
#define SERVICES_HEADERS_H
@@ -44,6 +63,7 @@
#include "pvr_debug.h"
#include "metrics.h"
#include "osfunc.h"
+#include "refcount.h"
-#endif
+#endif /* SERVICES_HEADERS_H */
diff --git a/sgx/services4/srvkm/include/srvkm.h b/sgx/services4/srvkm/include/srvkm.h
index 474a1ee..14828bd 100644
--- a/sgx/services4/srvkm/include/srvkm.h
+++ b/sgx/services4/srvkm/include/srvkm.h
@@ -1,28 +1,44 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Services kernel module internal header file
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef SRVKM_H
#define SRVKM_H
@@ -32,11 +48,12 @@
extern "C" {
#endif
-
+ /** Use PVR_DPF() unless message is necessary in release build
+ */
#ifdef PVR_DISABLE_LOGGING
#define PVR_LOG(X)
#else
-
+ /* PRQA S 3410 1 */ /* this macro requires no brackets in order to work */
#define PVR_LOG(X) PVRSRVReleasePrintf X;
#endif
@@ -58,7 +75,34 @@ extern "C" {
}
#endif
-
+/******************
+HIGHER LEVEL MACROS
+*******************/
+
+/*----------------------------------------------------------------------------
+Repeats the body of the loop for a certain minimum time, or until the body
+exits by its own means (break, return, goto, etc.)
+
+Example of usage:
+
+LOOP_UNTIL_TIMEOUT(MAX_HW_TIME_US)
+{
+ if(psQueueInfo->ui32ReadOffset == psQueueInfo->ui32WriteOffset)
+ {
+ bTimeout = IMG_FALSE;
+ break;
+ }
+
+ OSWaitus(MAX_HW_TIME_US/WAIT_TRY_COUNT);
+} END_LOOP_UNTIL_TIMEOUT();
+
+-----------------------------------------------------------------------------*/
+
+/* uiNotLastLoop will remain at 1 until the timeout has expired, at which time
+ * it will be decremented and the loop executed one final time. This is necessary
+ * when preemption is enabled.
+ */
+/* PRQA S 3411,3431 12 */ /* critical format, leave alone */
#define LOOP_UNTIL_TIMEOUT(TIMEOUT) \
{\
IMG_UINT32 uiOffset, uiStart, uiCurrent; \
@@ -72,7 +116,15 @@ extern "C" {
#define END_LOOP_UNTIL_TIMEOUT() \
}
+/*!
+ ******************************************************************************
+
+ @Function PVRSRVGetErrorStringKM
+
+ @Description Returns a text string relating to the PVRSRV_ERROR enum.
+
+ ******************************************************************************/
IMG_IMPORT
const IMG_CHAR *PVRSRVGetErrorStringKM(PVRSRV_ERROR eError);
-#endif
+#endif /* SRVKM_H */
diff --git a/sgx/services4/srvkm/include/ttrace.h b/sgx/services4/srvkm/include/ttrace.h
index 9e04b88..d073b7c 100644
--- a/sgx/services4/srvkm/include/ttrace.h
+++ b/sgx/services4/srvkm/include/ttrace.h
@@ -1,29 +1,46 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
-
+/*************************************************************************/ /*!
+@Title Timed Trace header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Timed Trace header. Contines structures and functions used
+ in the timed trace subsystem.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "services_headers.h"
#include "ttrace_common.h"
#include "ttrace_tokens.h"
@@ -147,7 +164,7 @@ static INLINE IMG_VOID PVRSRVTimeTraceSysPhysAddr(IMG_UINT32 ui32Group, IMG_UINT
1, (IMG_UINT8 *) &psPAddr.uiAddr);
}
-#else
+#else /* defined(PVRSRV_NEED_PVR_TIME_TRACE) */
#define PVR_TTRACE(group, class, token) \
((void) 0)
@@ -170,7 +187,7 @@ static INLINE IMG_VOID PVRSRVTimeTraceSysPhysAddr(IMG_UINT32 ui32Group, IMG_UINT
#define PVR_TTRACE_SYNC_OBJECT(group, token, syncobj, op) \
((void) 0)
-#endif
+#endif /* defined(PVRSRV_NEED_PVR_TIME_TRACE) */
IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceInit(IMG_VOID);
IMG_IMPORT IMG_VOID PVRSRVTimeTraceDeinit(IMG_VOID);
@@ -181,4 +198,4 @@ IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferCreate(IMG_UINT32 ui32PID);
IMG_IMPORT PVRSRV_ERROR PVRSRVTimeTraceBufferDestroy(IMG_UINT32 ui32PID);
IMG_IMPORT IMG_VOID PVRSRVDumpTimeTraceBuffers(IMG_VOID);
-#endif
+#endif /* __TTRACE_H__ */
diff --git a/sgx/services4/srvkm/include/ttrace_common.h b/sgx/services4/srvkm/include/ttrace_common.h
index 5895b6c..3e8b763 100644
--- a/sgx/services4/srvkm/include/ttrace_common.h
+++ b/sgx/services4/srvkm/include/ttrace_common.h
@@ -1,34 +1,96 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Timed Trace header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Timed Trace common header. Contains shared defines and
+ structures which are shared with the post processing tool.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#include "img_types.h"
#ifndef __TTRACE_COMMON_H__
#define __TTRACE_COMMON_H__
+/*
+ * Trace item
+ * ==========
+ *
+ * A trace item contains a trace header, a timestamp, a UID and a
+ * data header all of which are 32-bit and mandatory. If there
+ * is no data then the data header size is set to 0.
+ *
+ * Trace header
+ * ------------
+ * 31 27 23 19 15 11 7 3
+ * GGGG GGGG CCCC CCCC TTTT TTTT TTTT TTTT
+ *
+ * G = group
+ * Note:
+ * Group 0xff means the message is padding
+ *
+ * C = class
+ * T = Token
+ *
+ * Data header
+ *-----------
+ * 31 27 23 19 15 11 7 3
+ * SSSS SSSS SSSS SSSS TTTT CCCC CCCC CCCC
+ *
+ * S = data packet size
+ * T = Type
+ * 0000 - 8 bit
+ * 0001 - 16 bit
+ * 0010 - 32 bit
+ * 0011 - 64 bit
+ *
+ * C = data item count
+ *
+ * Note: It might look strange having both the packet
+ * size and the data item count, but the idea
+ * is the you might have a "special" data type
+ * who's size might not be known by the post
+ * processing program and rather then fail
+ * processing the buffer after that point if we
+ * know the size we can just skip it and move to
+ * the next item.
+ */
+
+
#define PVRSRV_TRACE_HEADER 0
#define PVRSRV_TRACE_TIMESTAMP 1
#define PVRSRV_TRACE_HOSTUID 2
@@ -62,6 +124,7 @@
#define TIME_TRACE_BUFFER_SIZE 4096
+/* Type defines for trace items */
#define PVRSRV_TRACE_TYPE_UI8 0
#define PVRSRV_TRACE_TYPE_UI16 1
#define PVRSRV_TRACE_TYPE_UI32 2
@@ -76,6 +139,9 @@
#define PVRSRV_TRACE_SYNC_WO_DEV_VADDR 5
#define PVRSRV_TRACE_SYNC_RO_DEV_VADDR 6
#define PVRSRV_TRACE_SYNC_OP 7
-#define PVRSRV_TRACE_TYPE_SYNC_SIZE ((PVRSRV_TRACE_SYNC_OP + 1) * sizeof(IMG_UINT32))
+ #define PVRSRV_TRACE_SYNC_RO2P 8
+ #define PVRSRV_TRACE_SYNC_RO2C 9
+ #define PVRSRV_TRACE_SYNC_RO2_DEV_VADDR 10
+#define PVRSRV_TRACE_TYPE_SYNC_SIZE ((PVRSRV_TRACE_SYNC_RO2_DEV_VADDR + 1) * sizeof(IMG_UINT32))
-#endif
+#endif /* __TTRACE_COMMON_H__*/
diff --git a/sgx/services4/srvkm/include/ttrace_tokens.h b/sgx/services4/srvkm/include/ttrace_tokens.h
index 21ea5fb..73323ad 100644
--- a/sgx/services4/srvkm/include/ttrace_tokens.h
+++ b/sgx/services4/srvkm/include/ttrace_tokens.h
@@ -1,32 +1,53 @@
-/**********************************************************************
- *
- * Copyright (C) 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.
- * 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
- *
- ******************************************************************************/
+/*************************************************************************/ /*!
+@Title Timed Trace header
+@Copyright Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+@Description Timed Trace token header. Contains defines for all the tokens
+ used.
+@License Dual MIT/GPLv2
+
+The contents of this file are subject to the MIT license as set out below.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+Alternatively, the contents of this file may be used under the terms of
+the GNU General Public License Version 2 ("GPL") in which case the provisions
+of GPL are applicable instead of those above.
+
+If you wish to allow use of your version of this file only under the terms of
+GPL, and not to allow others to use your version of this file under the terms
+of the MIT license, indicate your decision by deleting the provisions above
+and replace them with the notice and other provisions required by GPL as set
+out in the file called "GPL-COPYING" included in this distribution. If you do
+not delete the provisions above, a recipient may use your version of this file
+under the terms of either the MIT license or GPL.
+
+This License is also included in this distribution in the file called
+"MIT-COPYING".
+
+EXCEPT AS OTHERWISE STATED IN A NEGOTIATED AGREEMENT: (A) THE SOFTWARE IS
+PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
+BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+PURPOSE AND NONINFRINGEMENT; AND (B) IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+*/ /**************************************************************************/
#ifndef __TTRACE_TOKENS_H__
#define __TTRACE_TOKENS_H__
+/* All defines should use decimal so to not confuse the post processing tool */
+
+/* Trace groups */
#define PVRSRV_TRACE_GROUP_KICK 0
#define PVRSRV_TRACE_GROUP_TRANSFER 1
#define PVRSRV_TRACE_GROUP_QUEUE 2
@@ -35,6 +56,7 @@
#define PVRSRV_TRACE_GROUP_PADDING 255
+/* Trace classes */
#define PVRSRV_TRACE_CLASS_FUNCTION_ENTER 0
#define PVRSRV_TRACE_CLASS_FUNCTION_EXIT 1
#define PVRSRV_TRACE_CLASS_SYNC 2
@@ -46,10 +68,18 @@
#define PVRSRV_TRACE_CLASS_NONE 255
+/* Operation about to happen on the sync object */
#define PVRSRV_SYNCOP_SAMPLE 0
#define PVRSRV_SYNCOP_COMPLETE 1
#define PVRSRV_SYNCOP_DUMP 2
+/*
+ * Trace tokens
+ * ------------
+ * These only need to unique within a group.
+ */
+
+/* Kick group tokens */
#define KICK_TOKEN_DOKICK 0
#define KICK_TOKEN_CCB_OFFSET 1
#define KICK_TOKEN_TA3D_SYNC 2
@@ -58,6 +88,7 @@
#define KICK_TOKEN_SRC_SYNC 5
#define KICK_TOKEN_DST_SYNC 6
+/* Transfer Queue group tokens */
#define TRANSFER_TOKEN_SUBMIT 0
#define TRANSFER_TOKEN_TA_SYNC 1
#define TRANSFER_TOKEN_3D_SYNC 2
@@ -65,6 +96,7 @@
#define TRANSFER_TOKEN_DST_SYNC 4
#define TRANSFER_TOKEN_CCB_OFFSET 5
+/* Queue group tokens */
#define QUEUE_TOKEN_GET_SPACE 0
#define QUEUE_TOKEN_INSERTKM 1
#define QUEUE_TOKEN_SUBMITKM 2
@@ -77,8 +109,9 @@
#define QUEUE_TOKEN_DST_SYNC 9
#define QUEUE_TOKEN_COMMAND_TYPE 10
+/* uKernel Sync tokens */
#define MKSYNC_TOKEN_KERNEL_CCB_OFFSET 0
#define MKSYNC_TOKEN_CORE_CLK 1
#define MKSYNC_TOKEN_UKERNEL_CLK 2
-#endif
+#endif /* __TTRACE_TOKENS_H__ */