blob: ab6523a99270f8c38128ef5215fa23ef11e1f0b9 [file] [log] [blame]
/**********************************************************************
*
* 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>
#include "services_headers.h"
#include "sgx_bridge_km.h"
#include "sgxapi_km.h"
#include "sgxinfo.h"
#include "sgxinfokm.h"
#include "pvr_bridge_km.h"
#include "pdump_km.h"
#include "sgxutils.h"
#ifndef __linux__
#pragma message("TODO: Review use of OS_PAGEABLE vs OS_NON_PAGEABLE")
#endif
#include "lists.h"
static IMPLEMENT_LIST_INSERT(PVRSRV_STUB_PBDESC)
static IMPLEMENT_LIST_REMOVE(PVRSRV_STUB_PBDESC)
static PRESMAN_ITEM psResItemCreateSharedPB = IMG_NULL;
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);
IMG_EXPORT PVRSRV_ERROR
SGXFindSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
IMG_BOOL bLockOnFailure,
IMG_UINT32 ui32TotalPBSize,
IMG_HANDLE *phSharedPBDesc,
PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO **ppsHWPBDescKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO **ppsBlockKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO **ppsHWBlockKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO ***pppsSharedPBDescSubKernelMemInfos,
IMG_UINT32 *ui32SharedPBDescSubKernelMemInfosCount)
{
PVRSRV_STUB_PBDESC *psStubPBDesc;
PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos=IMG_NULL;
PVRSRV_SGXDEV_INFO *psSGXDevInfo;
PVRSRV_ERROR eError;
psSGXDevInfo = ((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
if (psStubPBDesc != IMG_NULL)
{
IMG_UINT32 i;
PRESMAN_ITEM psResItem;
if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
{
PVR_DPF((PVR_DBG_WARNING,
"SGXFindSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
}
if(OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
sizeof(PVRSRV_KERNEL_MEM_INFO *)
* psStubPBDesc->ui32SubKernelMemInfosCount,
(IMG_VOID **)&ppsSharedPBDescSubKernelMemInfos,
IMG_NULL,
"Array of Kernel Memory Info") != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: OSAllocMem failed"));
eError = PVRSRV_ERROR_OUT_OF_MEMORY;
goto ExitNotFound;
}
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_PB_DESC,
psStubPBDesc,
0,
&SGXCleanupSharedPBDescCallback);
if (psResItem == IMG_NULL)
{
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDesc->ui32SubKernelMemInfosCount,
ppsSharedPBDescSubKernelMemInfos,
0);
PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
goto ExitNotFound;
}
*ppsSharedPBDescKernelMemInfo = psStubPBDesc->psSharedPBDescKernelMemInfo;
*ppsHWPBDescKernelMemInfo = psStubPBDesc->psHWPBDescKernelMemInfo;
*ppsBlockKernelMemInfo = psStubPBDesc->psBlockKernelMemInfo;
*ppsHWBlockKernelMemInfo = psStubPBDesc->psHWBlockKernelMemInfo;
*ui32SharedPBDescSubKernelMemInfosCount =
psStubPBDesc->ui32SubKernelMemInfosCount;
*pppsSharedPBDescSubKernelMemInfos = ppsSharedPBDescSubKernelMemInfos;
for(i=0; i<psStubPBDesc->ui32SubKernelMemInfosCount; i++)
{
ppsSharedPBDescSubKernelMemInfos[i] =
psStubPBDesc->ppsSubKernelMemInfos[i];
}
psStubPBDesc->ui32RefCount++;
*phSharedPBDesc = (IMG_HANDLE)psResItem;
return PVRSRV_OK;
}
eError = PVRSRV_OK;
if (bLockOnFailure)
{
if (psResItemCreateSharedPB == IMG_NULL)
{
psResItemCreateSharedPB = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK,
psPerProc,
0,
&SGXCleanupSharedPBDescCreateLockCallback);
if (psResItemCreateSharedPB == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "SGXFindSharedPBDescKM: ResManRegisterRes failed"));
eError = PVRSRV_ERROR_UNABLE_TO_REGISTER_RESOURCE;
goto ExitNotFound;
}
PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
psPerProcCreateSharedPB = psPerProc;
}
else
{
eError = PVRSRV_ERROR_PROCESSING_BLOCKED;
}
}
ExitNotFound:
*phSharedPBDesc = IMG_NULL;
return eError;
}
static PVRSRV_ERROR
SGXCleanupSharedPBDescKM(PVRSRV_STUB_PBDESC *psStubPBDescIn)
{
IMG_UINT32 i;
PVRSRV_DEVICE_NODE *psDeviceNode;
psDeviceNode = (PVRSRV_DEVICE_NODE*)psStubPBDescIn->hDevCookie;
psStubPBDescIn->ui32RefCount--;
if (psStubPBDescIn->ui32RefCount == 0)
{
IMG_DEV_VIRTADDR sHWPBDescDevVAddr = psStubPBDescIn->sHWPBDescDevVAddr;
List_PVRSRV_STUB_PBDESC_Remove(psStubPBDescIn);
for(i=0 ; i<psStubPBDescIn->ui32SubKernelMemInfosCount; i++)
{
PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie,
psStubPBDescIn->ppsSubKernelMemInfos[i]);
}
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_KERNEL_MEM_INFO *) * psStubPBDescIn->ui32SubKernelMemInfosCount,
psStubPBDescIn->ppsSubKernelMemInfos,
0);
psStubPBDescIn->ppsSubKernelMemInfos = IMG_NULL;
PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psBlockKernelMemInfo);
PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWBlockKernelMemInfo);
PVRSRVFreeDeviceMemKM(psStubPBDescIn->hDevCookie, psStubPBDescIn->psHWPBDescKernelMemInfo);
PVRSRVFreeSharedSysMemoryKM(psStubPBDescIn->psSharedPBDescKernelMemInfo);
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_STUB_PBDESC),
psStubPBDescIn,
0);
SGXCleanupRequest(psDeviceNode,
&sHWPBDescDevVAddr,
PVRSRV_CLEANUPCMD_PB,
CLEANUP_WITH_POLL);
}
return PVRSRV_OK;
}
static PVRSRV_ERROR SGXCleanupSharedPBDescCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
{
PVRSRV_STUB_PBDESC *psStubPBDesc = (PVRSRV_STUB_PBDESC *)pvParam;
PVR_UNREFERENCED_PARAMETER(ui32Param);
PVR_UNREFERENCED_PARAMETER(bDummy);
return SGXCleanupSharedPBDescKM(psStubPBDesc);
}
static PVRSRV_ERROR SGXCleanupSharedPBDescCreateLockCallback(IMG_PVOID pvParam, IMG_UINT32 ui32Param, IMG_BOOL bDummy)
{
#ifdef DEBUG
PVRSRV_PER_PROCESS_DATA *psPerProc = (PVRSRV_PER_PROCESS_DATA *)pvParam;
PVR_ASSERT(psPerProc == psPerProcCreateSharedPB);
#else
PVR_UNREFERENCED_PARAMETER(pvParam);
#endif
PVR_UNREFERENCED_PARAMETER(ui32Param);
PVR_UNREFERENCED_PARAMETER(bDummy);
psPerProcCreateSharedPB = IMG_NULL;
psResItemCreateSharedPB = IMG_NULL;
return PVRSRV_OK;
}
IMG_EXPORT PVRSRV_ERROR
SGXUnrefSharedPBDescKM(IMG_HANDLE hSharedPBDesc)
{
PVR_ASSERT(hSharedPBDesc != IMG_NULL);
return ResManFreeResByPtr(hSharedPBDesc, CLEANUP_WITH_POLL);
}
IMG_EXPORT PVRSRV_ERROR
SGXAddSharedPBDescKM(PVRSRV_PER_PROCESS_DATA *psPerProc,
IMG_HANDLE hDevCookie,
PVRSRV_KERNEL_MEM_INFO *psSharedPBDescKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO *psHWPBDescKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO *psBlockKernelMemInfo,
PVRSRV_KERNEL_MEM_INFO *psHWBlockKernelMemInfo,
IMG_UINT32 ui32TotalPBSize,
IMG_HANDLE *phSharedPBDesc,
PVRSRV_KERNEL_MEM_INFO **ppsSharedPBDescSubKernelMemInfos,
IMG_UINT32 ui32SharedPBDescSubKernelMemInfosCount,
IMG_DEV_VIRTADDR sHWPBDescDevVAddr)
{
PVRSRV_STUB_PBDESC *psStubPBDesc=IMG_NULL;
PVRSRV_ERROR eRet = PVRSRV_ERROR_INVALID_PERPROC;
IMG_UINT32 i;
PVRSRV_SGXDEV_INFO *psSGXDevInfo;
PRESMAN_ITEM psResItem;
if (psPerProcCreateSharedPB != psPerProc)
{
goto NoAdd;
}
else
{
PVR_ASSERT(psResItemCreateSharedPB != IMG_NULL);
ResManFreeResByPtr(psResItemCreateSharedPB, CLEANUP_WITH_POLL);
PVR_ASSERT(psResItemCreateSharedPB == IMG_NULL);
PVR_ASSERT(psPerProcCreateSharedPB == IMG_NULL);
}
psSGXDevInfo = (PVRSRV_SGXDEV_INFO *)((PVRSRV_DEVICE_NODE *)hDevCookie)->pvDevice;
psStubPBDesc = psSGXDevInfo->psStubPBDescListKM;
if (psStubPBDesc != IMG_NULL)
{
if(psStubPBDesc->ui32TotalPBSize != ui32TotalPBSize)
{
PVR_DPF((PVR_DBG_WARNING,
"SGXAddSharedPBDescKM: Shared PB requested with different size (0x%x) from existing shared PB (0x%x) - requested size ignored",
ui32TotalPBSize, psStubPBDesc->ui32TotalPBSize));
}
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_PB_DESC,
psStubPBDesc,
0,
&SGXCleanupSharedPBDescCallback);
if (psResItem == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR,
"SGXAddSharedPBDescKM: "
"Failed to register existing shared "
"PBDesc with the resource manager"));
goto NoAddKeepPB;
}
psStubPBDesc->ui32RefCount++;
*phSharedPBDesc = (IMG_HANDLE)psResItem;
eRet = PVRSRV_OK;
goto NoAddKeepPB;
}
if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_STUB_PBDESC),
(IMG_VOID **)&psStubPBDesc,
0,
"Stub Parameter Buffer Description") != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: Failed to alloc "
"StubPBDesc"));
eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
goto NoAdd;
}
psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
if(OSAllocMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_KERNEL_MEM_INFO *)
* ui32SharedPBDescSubKernelMemInfosCount,
(IMG_VOID **)&psStubPBDesc->ppsSubKernelMemInfos,
0,
"Array of Kernel Memory Info") != PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
"Failed to alloc "
"StubPBDesc->ppsSubKernelMemInfos"));
eRet = PVRSRV_ERROR_OUT_OF_MEMORY;
goto NoAdd;
}
if(PVRSRVDissociateMemFromResmanKM(psSharedPBDescKernelMemInfo)
!= PVRSRV_OK)
{
goto NoAdd;
}
if(PVRSRVDissociateMemFromResmanKM(psHWPBDescKernelMemInfo)
!= PVRSRV_OK)
{
goto NoAdd;
}
if(PVRSRVDissociateMemFromResmanKM(psBlockKernelMemInfo)
!= PVRSRV_OK)
{
goto NoAdd;
}
if(PVRSRVDissociateMemFromResmanKM(psHWBlockKernelMemInfo)
!= PVRSRV_OK)
{
goto NoAdd;
}
psStubPBDesc->ui32RefCount = 1;
psStubPBDesc->ui32TotalPBSize = ui32TotalPBSize;
psStubPBDesc->psSharedPBDescKernelMemInfo = psSharedPBDescKernelMemInfo;
psStubPBDesc->psHWPBDescKernelMemInfo = psHWPBDescKernelMemInfo;
psStubPBDesc->psBlockKernelMemInfo = psBlockKernelMemInfo;
psStubPBDesc->psHWBlockKernelMemInfo = psHWBlockKernelMemInfo;
psStubPBDesc->ui32SubKernelMemInfosCount =
ui32SharedPBDescSubKernelMemInfosCount;
for(i=0; i<ui32SharedPBDescSubKernelMemInfosCount; i++)
{
psStubPBDesc->ppsSubKernelMemInfos[i] = ppsSharedPBDescSubKernelMemInfos[i];
if(PVRSRVDissociateMemFromResmanKM(ppsSharedPBDescSubKernelMemInfos[i])
!= PVRSRV_OK)
{
PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
"Failed to dissociate shared PBDesc "
"from process"));
goto NoAdd;
}
}
psStubPBDesc->sHWPBDescDevVAddr = sHWPBDescDevVAddr;
psResItem = ResManRegisterRes(psPerProc->hResManContext,
RESMAN_TYPE_SHARED_PB_DESC,
psStubPBDesc,
0,
&SGXCleanupSharedPBDescCallback);
if (psResItem == IMG_NULL)
{
PVR_DPF((PVR_DBG_ERROR, "SGXAddSharedPBDescKM: "
"Failed to register shared PBDesc "
" with the resource manager"));
goto NoAdd;
}
psStubPBDesc->hDevCookie = hDevCookie;
List_PVRSRV_STUB_PBDESC_Insert(&(psSGXDevInfo->psStubPBDescListKM),
psStubPBDesc);
*phSharedPBDesc = (IMG_HANDLE)psResItem;
return PVRSRV_OK;
NoAdd:
if(psStubPBDesc)
{
if(psStubPBDesc->ppsSubKernelMemInfos)
{
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_KERNEL_MEM_INFO *) * ui32SharedPBDescSubKernelMemInfosCount,
psStubPBDesc->ppsSubKernelMemInfos,
0);
psStubPBDesc->ppsSubKernelMemInfos = IMG_NULL;
}
OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
sizeof(PVRSRV_STUB_PBDESC),
psStubPBDesc,
0);
}
NoAddKeepPB:
for (i = 0; i < ui32SharedPBDescSubKernelMemInfosCount; i++)
{
PVRSRVFreeDeviceMemKM(hDevCookie, ppsSharedPBDescSubKernelMemInfos[i]);
}
PVRSRVFreeSharedSysMemoryKM(psSharedPBDescKernelMemInfo);
PVRSRVFreeDeviceMemKM(hDevCookie, psHWPBDescKernelMemInfo);
PVRSRVFreeSharedSysMemoryKM(psBlockKernelMemInfo);
PVRSRVFreeDeviceMemKM(hDevCookie, psHWBlockKernelMemInfo);
return eRet;
}