1 /**********************************************************************
2 Copyright (c) Imagination Technologies Ltd.
4 Permission is hereby granted, free of charge, to any person obtaining a copy
5 of this software and associated documentation files (the "Software"), to deal
6 in the Software without restriction, including without limitation the rights
7 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the Software is
9 furnished to do so, subject to the following conditions:
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 ******************************************************************************/
23 #include "services_headers.h"
28 #include <linux/version.h>
29 #include <linux/sched.h>
30 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,9)
31 #include <linux/hardirq.h>
33 #include <asm/hardirq.h>
36 static DEFINE_MUTEX(lock);
38 #define ACQUIRE_SYNC_OBJ do { \
39 if (in_interrupt()) { \
40 printk ("ISR cannot take RESMAN mutex\n"); \
43 else mutex_lock(&lock); \
45 #define RELEASE_SYNC_OBJ mutex_unlock(&lock)
49 #define ACQUIRE_SYNC_OBJ
50 #define RELEASE_SYNC_OBJ
54 #define RESMAN_SIGNATURE 0x12345678
56 typedef struct _RESMAN_ITEM_
59 IMG_UINT32 ui32Signature;
61 struct _RESMAN_ITEM_ **ppsThis;
62 struct _RESMAN_ITEM_ *psNext;
65 IMG_UINT32 ui32ResType;
70 RESMAN_FREE_FN pfnFreeResource;
74 typedef struct _RESMAN_CONTEXT_
77 IMG_UINT32 ui32Signature;
79 struct _RESMAN_CONTEXT_ **ppsThis;
80 struct _RESMAN_CONTEXT_ *psNext;
82 PVRSRV_PER_PROCESS_DATA *psPerProc;
84 RESMAN_ITEM *psResItemList;
91 RESMAN_CONTEXT *psContextList;
93 } RESMAN_LIST, *PRESMAN_LIST;
96 PRESMAN_LIST gpsResList = IMG_NULL;
100 static IMPLEMENT_LIST_ANY_VA(RESMAN_ITEM)
101 static IMPLEMENT_LIST_ANY_VA_2(RESMAN_ITEM, IMG_BOOL, IMG_FALSE)
102 static IMPLEMENT_LIST_INSERT(RESMAN_ITEM)
103 static IMPLEMENT_LIST_REMOVE(RESMAN_ITEM)
105 static IMPLEMENT_LIST_REMOVE(RESMAN_CONTEXT)
106 static IMPLEMENT_LIST_INSERT(RESMAN_CONTEXT)
109 #define PRINT_RESLIST(x, y, z)
111 static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem, IMG_BOOL bExecuteCallback);
113 static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psContext,
114 IMG_UINT32 ui32SearchCriteria,
115 IMG_UINT32 ui32ResType,
117 IMG_UINT32 ui32Param,
118 IMG_BOOL bExecuteCallback);
122 static IMG_VOID ValidateResList(PRESMAN_LIST psResList);
123 #define VALIDATERESLIST() ValidateResList(gpsResList)
125 #define VALIDATERESLIST()
133 PVRSRV_ERROR ResManInit(IMG_VOID)
135 if (gpsResList == IMG_NULL)
138 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
140 (IMG_VOID **)&gpsResList, IMG_NULL,
141 "Resource Manager List") != PVRSRV_OK)
143 return PVRSRV_ERROR_OUT_OF_MEMORY;
147 gpsResList->psContextList = IMG_NULL;
157 IMG_VOID ResManDeInit(IMG_VOID)
159 if (gpsResList != IMG_NULL)
162 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*gpsResList), gpsResList, IMG_NULL);
163 gpsResList = IMG_NULL;
168 PVRSRV_ERROR PVRSRVResManConnect(IMG_HANDLE hPerProc,
169 PRESMAN_CONTEXT *phResManContext)
172 PRESMAN_CONTEXT psResManContext;
181 eError = OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(*psResManContext),
182 (IMG_VOID **)&psResManContext, IMG_NULL,
183 "Resource Manager Context");
184 if (eError != PVRSRV_OK)
186 PVR_DPF((PVR_DBG_ERROR, "PVRSRVResManConnect: ERROR allocating new RESMAN context struct"));
198 psResManContext->ui32Signature = RESMAN_SIGNATURE;
200 psResManContext->psResItemList = IMG_NULL;
201 psResManContext->psPerProc = hPerProc;
204 List_RESMAN_CONTEXT_Insert(&gpsResList->psContextList, psResManContext);
212 *phResManContext = psResManContext;
218 IMG_VOID PVRSRVResManDisconnect(PRESMAN_CONTEXT psResManContext,
219 IMG_BOOL bKernelContext)
228 PRINT_RESLIST(gpsResList, psResManContext, IMG_TRUE);
235 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_OS_USERMODE_MAPPING, 0, 0, IMG_TRUE);
238 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_EVENT_OBJECT, 0, 0, IMG_TRUE);
241 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_MODIFY_SYNC_OPS, 0, 0, IMG_TRUE);
244 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_RENDER_CONTEXT, 0, 0, IMG_TRUE);
245 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
246 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_HW_2D_CONTEXT, 0, 0, IMG_TRUE);
247 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_TRANSFER_CONTEXT, 0, 0, IMG_TRUE);
248 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC_CREATE_LOCK, 0, 0, IMG_TRUE);
249 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_SHARED_PB_DESC, 0, 0, IMG_TRUE);
254 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_SWAPCHAIN_REF, 0, 0, IMG_TRUE);
255 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DISPLAYCLASS_DEVICE, 0, 0, IMG_TRUE);
258 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_BUFFERCLASS_DEVICE, 0, 0, IMG_TRUE);
261 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICECLASSMEM_MAPPING, 0, 0, IMG_TRUE);
262 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_WRAP, 0, 0, IMG_TRUE);
263 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_MAPPING, 0, 0, IMG_TRUE);
264 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_KERNEL_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
265 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_ALLOCATION, 0, 0, IMG_TRUE);
266 FreeResourceByCriteria(psResManContext, RESMAN_CRITERIA_RESTYPE, RESMAN_TYPE_DEVICEMEM_CONTEXT, 0, 0, IMG_TRUE);
270 PVR_ASSERT(psResManContext->psResItemList == IMG_NULL);
273 List_RESMAN_CONTEXT_Remove(psResManContext);
276 OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_CONTEXT), psResManContext, IMG_NULL);
284 PRINT_RESLIST(gpsResList, psResManContext, IMG_FALSE);
291 PRESMAN_ITEM ResManRegisterRes(PRESMAN_CONTEXT psResManContext,
292 IMG_UINT32 ui32ResType,
294 IMG_UINT32 ui32Param,
295 RESMAN_FREE_FN pfnFreeResource)
297 PRESMAN_ITEM psNewResItem;
299 PVR_ASSERT(psResManContext != IMG_NULL);
300 PVR_ASSERT(ui32ResType != 0);
302 if (psResManContext == IMG_NULL)
304 PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: invalid parameter - psResManContext"));
305 return (PRESMAN_ITEM) IMG_NULL;
314 PVR_DPF((PVR_DBG_MESSAGE, "ResManRegisterRes: register resource "
315 "Context 0x%x, ResType 0x%x, pvParam 0x%x, ui32Param 0x%x, "
317 psResManContext, ui32ResType, (IMG_UINT32)pvParam,
318 ui32Param, pfnFreeResource));
321 if (OSAllocMem(PVRSRV_OS_PAGEABLE_HEAP,
322 sizeof(RESMAN_ITEM), (IMG_VOID **)&psNewResItem,
324 "Resource Manager Item") != PVRSRV_OK)
326 PVR_DPF((PVR_DBG_ERROR, "ResManRegisterRes: "
327 "ERROR allocating new resource item"));
332 return((PRESMAN_ITEM)IMG_NULL);
337 psNewResItem->ui32Signature = RESMAN_SIGNATURE;
339 psNewResItem->ui32ResType = ui32ResType;
340 psNewResItem->pvParam = pvParam;
341 psNewResItem->ui32Param = ui32Param;
342 psNewResItem->pfnFreeResource = pfnFreeResource;
343 psNewResItem->ui32Flags = 0;
346 List_RESMAN_ITEM_Insert(&psResManContext->psResItemList, psNewResItem);
354 return(psNewResItem);
357 PVRSRV_ERROR ResManFreeResByPtr(RESMAN_ITEM *psResItem)
361 PVR_ASSERT(psResItem != IMG_NULL);
363 if (psResItem == IMG_NULL)
365 PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: NULL ptr - nothing to do"));
369 PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByPtr: freeing resource at %08X", psResItem));
378 eError = FreeResourceByPtr(psResItem, IMG_TRUE);
390 PVRSRV_ERROR ResManFreeResByCriteria(PRESMAN_CONTEXT psResManContext,
391 IMG_UINT32 ui32SearchCriteria,
392 IMG_UINT32 ui32ResType,
394 IMG_UINT32 ui32Param)
398 PVR_ASSERT(psResManContext != IMG_NULL);
406 PVR_DPF((PVR_DBG_MESSAGE, "ResManFreeResByCriteria: "
407 "Context 0x%x, Criteria 0x%x, Type 0x%x, Addr 0x%x, Param 0x%x",
408 psResManContext, ui32SearchCriteria, ui32ResType,
409 (IMG_UINT32)pvParam, ui32Param));
412 eError = FreeResourceByCriteria(psResManContext, ui32SearchCriteria,
413 ui32ResType, pvParam, ui32Param,
426 PVRSRV_ERROR ResManDissociateRes(RESMAN_ITEM *psResItem,
427 PRESMAN_CONTEXT psNewResManContext)
429 PVRSRV_ERROR eError = PVRSRV_OK;
431 PVR_ASSERT(psResItem != IMG_NULL);
433 if (psResItem == IMG_NULL)
435 PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: invalid parameter - psResItem"));
437 return PVRSRV_ERROR_INVALID_PARAMS;
441 PVR_ASSERT(psResItem->ui32Signature == RESMAN_SIGNATURE);
444 if (psNewResManContext != IMG_NULL)
447 List_RESMAN_ITEM_Remove(psResItem);
450 List_RESMAN_ITEM_Insert(&psNewResManContext->psResItemList, psResItem);
455 eError = FreeResourceByPtr(psResItem, IMG_FALSE);
456 if(eError != PVRSRV_OK)
458 PVR_DPF((PVR_DBG_ERROR, "ResManDissociateRes: failed to free resource by pointer"));
466 IMG_BOOL ResManFindResourceByPtr_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
470 psItem = va_arg(va, RESMAN_ITEM*);
472 return (IMG_BOOL)(psCurItem == psItem);
476 IMG_INTERNAL PVRSRV_ERROR ResManFindResourceByPtr(PRESMAN_CONTEXT psResManContext,
479 PVRSRV_ERROR eResult;
481 PVR_ASSERT(psResManContext != IMG_NULL);
482 PVR_ASSERT(psItem != IMG_NULL);
484 if ((psItem == IMG_NULL) || (psResManContext == IMG_NULL))
486 PVR_DPF((PVR_DBG_ERROR, "ResManFindResourceByPtr: invalid parameter"));
488 return PVRSRV_ERROR_INVALID_PARAMS;
492 PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
498 PVR_DPF((PVR_DBG_MESSAGE,
499 "FindResourceByPtr: psItem=%08X, psItem->psNext=%08X",
500 psItem, psItem->psNext));
502 PVR_DPF((PVR_DBG_MESSAGE,
503 "FindResourceByPtr: Resource Ctx 0x%x, Type 0x%x, Addr 0x%x, "
504 "Param 0x%x, FnCall %08X, Flags 0x%x",
506 psItem->ui32ResType, (IMG_UINT32)psItem->pvParam, psItem->ui32Param,
507 psItem->pfnFreeResource, psItem->ui32Flags));
510 if(List_RESMAN_ITEM_IMG_BOOL_Any_va(psResManContext->psResItemList,
511 ResManFindResourceByPtr_AnyVaCb,
518 eResult = PVRSRV_ERROR_NOT_OWNER;
527 static PVRSRV_ERROR FreeResourceByPtr(RESMAN_ITEM *psItem,
528 IMG_BOOL bExecuteCallback)
530 PVRSRV_ERROR eError = PVRSRV_OK;
532 PVR_ASSERT(psItem != IMG_NULL);
534 if (psItem == IMG_NULL)
536 PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: invalid parameter"));
537 return PVRSRV_ERROR_INVALID_PARAMS;
541 PVR_ASSERT(psItem->ui32Signature == RESMAN_SIGNATURE);
544 PVR_DPF((PVR_DBG_MESSAGE,
545 "FreeResourceByPtr: psItem=%08X, psItem->psNext=%08X",
546 psItem, psItem->psNext));
548 PVR_DPF((PVR_DBG_MESSAGE,
549 "FreeResourceByPtr: Type 0x%x, Addr 0x%x, "
550 "Param 0x%x, FnCall %08X, Flags 0x%x",
551 psItem->ui32ResType, (IMG_UINT32)psItem->pvParam, psItem->ui32Param,
552 psItem->pfnFreeResource, psItem->ui32Flags));
555 List_RESMAN_ITEM_Remove(psItem);
562 if (bExecuteCallback)
564 eError = psItem->pfnFreeResource(psItem->pvParam, psItem->ui32Param);
565 if (eError != PVRSRV_OK)
567 PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR calling FreeResource function"));
575 if(OSFreeMem(PVRSRV_OS_PAGEABLE_HEAP, sizeof(RESMAN_ITEM), psItem, IMG_NULL) != PVRSRV_OK)
577 PVR_DPF((PVR_DBG_ERROR, "FreeResourceByPtr: ERROR freeing resource list item memory"));
578 eError = PVRSRV_ERROR_GENERIC;
584 IMG_VOID* FreeResourceByCriteria_AnyVaCb(RESMAN_ITEM *psCurItem, va_list va)
586 IMG_UINT32 ui32SearchCriteria;
587 IMG_UINT32 ui32ResType;
589 IMG_UINT32 ui32Param;
591 ui32SearchCriteria = va_arg(va, IMG_UINT32);
592 ui32ResType = va_arg(va, IMG_UINT32);
593 pvParam = va_arg(va, IMG_PVOID);
594 ui32Param = va_arg(va, IMG_UINT32);
599 (((ui32SearchCriteria & RESMAN_CRITERIA_RESTYPE) == 0UL) ||
600 (psCurItem->ui32ResType == ui32ResType))
603 (((ui32SearchCriteria & RESMAN_CRITERIA_PVOID_PARAM) == 0UL) ||
604 (psCurItem->pvParam == pvParam))
607 (((ui32SearchCriteria & RESMAN_CRITERIA_UI32_PARAM) == 0UL) ||
608 (psCurItem->ui32Param == ui32Param))
619 static PVRSRV_ERROR FreeResourceByCriteria(PRESMAN_CONTEXT psResManContext,
620 IMG_UINT32 ui32SearchCriteria,
621 IMG_UINT32 ui32ResType,
623 IMG_UINT32 ui32Param,
624 IMG_BOOL bExecuteCallback)
626 PRESMAN_ITEM psCurItem;
627 PVRSRV_ERROR eError = PVRSRV_OK;
631 while((psCurItem = (PRESMAN_ITEM)
632 List_RESMAN_ITEM_Any_va(psResManContext->psResItemList,
633 FreeResourceByCriteria_AnyVaCb,
637 ui32Param)) != IMG_NULL
638 && eError == PVRSRV_OK)
640 eError = FreeResourceByPtr(psCurItem, bExecuteCallback);
648 static IMG_VOID ValidateResList(PRESMAN_LIST psResList)
650 PRESMAN_ITEM psCurItem, *ppsThisItem;
651 PRESMAN_CONTEXT psCurContext, *ppsThisContext;
654 if (psResList == IMG_NULL)
656 PVR_DPF((PVR_DBG_MESSAGE, "ValidateResList: resman not initialised yet"));
660 psCurContext = psResList->psContextList;
661 ppsThisContext = &psResList->psContextList;
664 while(psCurContext != IMG_NULL)
667 PVR_ASSERT(psCurContext->ui32Signature == RESMAN_SIGNATURE);
668 if (psCurContext->ppsThis != ppsThisContext)
670 PVR_DPF((PVR_DBG_WARNING,
671 "psCC=%08X psCC->ppsThis=%08X psCC->psNext=%08X ppsTC=%08X",
672 psCurContext, psCurContext->ppsThis,
673 psCurContext->psNext, ppsThisContext));
674 PVR_ASSERT(psCurContext->ppsThis == ppsThisContext);
678 psCurItem = psCurContext->psResItemList;
679 ppsThisItem = &psCurContext->psResItemList;
680 while(psCurItem != IMG_NULL)
683 PVR_ASSERT(psCurItem->ui32Signature == RESMAN_SIGNATURE);
684 if (psCurItem->ppsThis != ppsThisItem)
686 PVR_DPF((PVR_DBG_WARNING,
687 "psCurItem=%08X psCurItem->ppsThis=%08X psCurItem->psNext=%08X ppsThisItem=%08X",
688 psCurItem, psCurItem->ppsThis, psCurItem->psNext, ppsThisItem));
689 PVR_ASSERT(psCurItem->ppsThis == ppsThisItem);
693 ppsThisItem = &psCurItem->psNext;
694 psCurItem = psCurItem->psNext;
698 ppsThisContext = &psCurContext->psNext;
699 psCurContext = psCurContext->psNext;