1 /****************************************************************************
3 * Copyright (C) 2005 - 2013 by Vivante Corp.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the license, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *****************************************************************************/
22 #include "gc_hal_kernel_linux.h"
24 #include <linux/pagemap.h>
25 #include <linux/seq_file.h>
27 #include <linux/mman.h>
28 #include <linux/sched.h>
29 #include <asm/atomic.h>
30 #include <linux/dma-mapping.h>
31 #include <linux/slab.h>
32 #include <linux/idr.h>
33 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
34 #include <mach/hardware.h>
36 #include <linux/workqueue.h>
37 #include <linux/idr.h>
38 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
39 #include <linux/math64.h>
41 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
42 #include <linux/reset.h>
43 static inline void imx_gpc_power_up_pu(bool flag) {}
44 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
45 #include <mach/common.h>
47 #include <linux/delay.h>
48 #include <linux/pm_runtime.h>
51 #if gcdANDROID_NATIVE_FENCE_SYNC
52 #include <linux/file.h>
53 #include "gc_hal_kernel_sync.h"
57 #define _GC_OBJ_ZONE gcvZONE_OS
59 /*******************************************************************************
60 ***** Version Signature *******************************************************/
63 const char * _PLATFORM = "\n\0$PLATFORM$Android$\n";
65 const char * _PLATFORM = "\n\0$PLATFORM$Linux$\n";
68 #define USER_SIGNAL_TABLE_LEN_INIT 64
69 #define gcdSUPPRESS_OOM_MESSAGE 1
71 #define MEMORY_LOCK(os) \
72 gcmkVERIFY_OK(gckOS_AcquireMutex( \
77 #define MEMORY_UNLOCK(os) \
78 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
80 #define MEMORY_MAP_LOCK(os) \
81 gcmkVERIFY_OK(gckOS_AcquireMutex( \
83 (os)->memoryMapLock, \
86 #define MEMORY_MAP_UNLOCK(os) \
87 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
89 /* Protection bit when mapping memroy to user sapce */
90 #define gcmkPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
92 #if gcdNONPAGED_MEMORY_BUFFERABLE
93 #define gcmkIOREMAP ioremap_wc
94 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_writecombine(x)
95 #elif !gcdNONPAGED_MEMORY_CACHEABLE
96 #define gcmkIOREMAP ioremap_nocache
97 #define gcmkNONPAGED_MEMROY_PROT(x) pgprot_noncached(x)
100 #if gcdSUPPRESS_OOM_MESSAGE
101 #define gcdNOWARN __GFP_NOWARN
106 #define gcdINFINITE_TIMEOUT (60 * 1000)
107 #define gcdDETECT_TIMEOUT 0
108 #define gcdDETECT_DMA_ADDRESS 1
109 #define gcdDETECT_DMA_STATE 1
111 #define gcdUSE_NON_PAGED_MEMORY_CACHE 10
113 /******************************************************************************\
114 ********************************** Structures **********************************
115 \******************************************************************************/
116 #if gcdUSE_NON_PAGED_MEMORY_CACHE
117 typedef struct _gcsNonPagedMemoryCache
119 #ifndef NO_DMA_COHERENT
122 dma_addr_t dmaHandle;
128 struct _gcsNonPagedMemoryCache * prev;
129 struct _gcsNonPagedMemoryCache * next;
131 gcsNonPagedMemoryCache;
132 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
134 typedef struct _gcsUSER_MAPPING * gcsUSER_MAPPING_PTR;
135 typedef struct _gcsUSER_MAPPING
137 /* Pointer to next mapping structure. */
138 gcsUSER_MAPPING_PTR next;
140 /* Physical address of this mapping. */
143 /* Logical address of this mapping. */
146 /* Number of bytes of this mapping. */
149 /* Starting address of this mapping. */
152 /* Ending address of this mapping. */
157 typedef struct _gcsINTEGER_DB * gcsINTEGER_DB_PTR;
158 typedef struct _gcsINTEGER_DB
174 /* Pointer to device */
177 /* Memory management */
178 gctPOINTER memoryLock;
179 gctPOINTER memoryMapLock;
181 struct _LINUX_MDL *mdlHead;
182 struct _LINUX_MDL *mdlTail;
184 /* Kernel process ID. */
185 gctUINT32 kernelProcessID;
187 /* Signal management. */
190 gctPOINTER signalMutex;
192 /* signal id database. */
193 gcsINTEGER_DB signalDB;
195 #if gcdANDROID_NATIVE_FENCE_SYNC
197 gctPOINTER syncPointMutex;
199 /* sync point id database. */
200 gcsINTEGER_DB syncPointDB;
203 gcsUSER_MAPPING_PTR userMap;
204 gctPOINTER debugLock;
206 #if gcdUSE_NON_PAGED_MEMORY_CACHE
208 gcsNonPagedMemoryCache * cacheHead;
209 gcsNonPagedMemoryCache * cacheTail;
212 /* workqueue for os timer. */
213 struct workqueue_struct * workqueue;
216 typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
217 typedef struct _gcsSIGNAL
219 /* Kernel sync primitive. */
220 struct completion obj;
222 /* Manual reset flag. */
225 /* The reference counter. */
228 /* The owner of the signal. */
231 gckHARDWARE hardware;
238 #if gcdANDROID_NATIVE_FENCE_SYNC
239 typedef struct _gcsSYNC_POINT * gcsSYNC_POINT_PTR;
240 typedef struct _gcsSYNC_POINT
242 /* The reference counter. */
249 struct sync_timeline * timeline;
257 typedef struct _gcsPageInfo * gcsPageInfo_PTR;
258 typedef struct _gcsPageInfo
261 gctUINT32_PTR pageTable;
265 typedef struct _gcsOSTIMER * gcsOSTIMER_PTR;
266 typedef struct _gcsOSTIMER
268 struct delayed_work work;
269 gctTIMERFUNCTION function;
273 /******************************************************************************\
274 ******************************* Private Functions ******************************
275 \******************************************************************************/
282 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
283 return task_tgid_vnr(current);
285 return current->tgid;
294 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
295 return task_pid_vnr(current);
308 gcmkHEADER_ARG("ProcessID=%d", ProcessID);
310 mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
317 mdl->pid = ProcessID;
322 gcmkFOOTER_ARG("0x%X", mdl);
329 IN PLINUX_MDL_MAP MdlMap
337 PLINUX_MDL_MAP mdlMap, next;
339 gcmkHEADER_ARG("Mdl=0x%X", Mdl);
341 /* Verify the arguments. */
342 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
346 while (mdlMap != gcvNULL)
350 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
361 static PLINUX_MDL_MAP
367 PLINUX_MDL_MAP mdlMap;
369 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
371 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
372 if (mdlMap == gcvNULL)
378 mdlMap->pid = ProcessID;
379 mdlMap->vmaAddr = gcvNULL;
380 mdlMap->vma = gcvNULL;
383 mdlMap->next = Mdl->maps;
386 gcmkFOOTER_ARG("0x%X", mdlMap);
393 IN PLINUX_MDL_MAP MdlMap
396 PLINUX_MDL_MAP prevMdlMap;
398 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
400 /* Verify the arguments. */
401 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
402 gcmkASSERT(Mdl->maps != gcvNULL);
404 if (Mdl->maps == MdlMap)
406 Mdl->maps = MdlMap->next;
410 prevMdlMap = Mdl->maps;
412 while (prevMdlMap->next != MdlMap)
414 prevMdlMap = prevMdlMap->next;
416 gcmkASSERT(prevMdlMap != gcvNULL);
419 prevMdlMap->next = MdlMap->next;
428 extern PLINUX_MDL_MAP
434 PLINUX_MDL_MAP mdlMap;
436 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
444 while (mdlMap != gcvNULL)
446 if (mdlMap->pid == ProcessID)
448 gcmkFOOTER_ARG("0x%X", mdlMap);
452 mdlMap = mdlMap->next;
467 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
473 unsigned long addr = (unsigned long)Addr;
475 return addr >= VMALLOC_START && addr < VMALLOC_END;
481 IN struct page ** Pages,
482 IN gctUINT32 NumPages
487 gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
489 gcmkASSERT(Pages != gcvNULL);
491 for (i = 0; i < NumPages; i++)
493 __free_page(Pages[i]);
496 if (is_vmalloc_addr(Pages))
508 static struct page **
510 IN gctUINT32 NumPages
513 struct page ** pages;
517 gcmkHEADER_ARG("NumPages=%lu", NumPages);
519 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
520 if (NumPages > totalram_pages)
522 if (NumPages > num_physpages)
529 size = NumPages * sizeof(struct page *);
531 pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
535 pages = vmalloc(size);
544 for (i = 0; i < NumPages; i++)
546 p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
550 _NonContiguousFree(pages, i);
558 gcmkFOOTER_ARG("pages=0x%X", pages);
562 static inline struct page *
563 _NonContiguousToPage(
564 IN struct page ** Pages,
568 gcmkASSERT(Pages != gcvNULL);
572 static inline unsigned long
574 IN struct page ** Pages,
578 gcmkASSERT(Pages != gcvNULL);
579 return page_to_pfn(_NonContiguousToPage(Pages, Index));
582 static inline unsigned long
583 _NonContiguousToPhys(
584 IN struct page ** Pages,
588 gcmkASSERT(Pages != gcvNULL);
589 return page_to_phys(_NonContiguousToPage(Pages, Index));
593 #if gcdUSE_NON_PAGED_MEMORY_CACHE
596 _AddNonPagedMemoryCache(
598 #ifndef NO_DMA_COHERENT
608 gcsNonPagedMemoryCache *cache;
610 if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
615 /* Allocate the cache record */
616 cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
618 if (cache == gcvNULL) return gcvFALSE;
620 #ifndef NO_DMA_COHERENT
623 cache->dmaHandle = DmaHandle;
625 cache->order = Order;
630 if (Os->cacheHead == gcvNULL)
632 cache->prev = gcvNULL;
633 cache->next = gcvNULL;
635 Os->cacheTail = cache;
639 /* Add to the tail. */
640 cache->prev = Os->cacheTail;
641 cache->next = gcvNULL;
642 Os->cacheTail->next = cache;
643 Os->cacheTail = cache;
651 #ifndef NO_DMA_COHERENT
653 _GetNonPagedMemoryCache(
656 dma_addr_t * DmaHandle
660 _GetNonPagedMemoryCache(
666 gcsNonPagedMemoryCache *cache;
667 #ifndef NO_DMA_COHERENT
673 if (Os->cacheHead == gcvNULL) return gcvNULL;
675 /* Find the right cache */
676 cache = Os->cacheHead;
678 while (cache != gcvNULL)
680 #ifndef NO_DMA_COHERENT
681 if (cache->size == Size) break;
683 if (cache->order == Order) break;
689 if (cache == gcvNULL) return gcvNULL;
691 /* Remove the cache from list */
692 if (cache == Os->cacheHead)
694 Os->cacheHead = cache->next;
696 if (Os->cacheHead == gcvNULL)
698 Os->cacheTail = gcvNULL;
703 cache->prev->next = cache->next;
705 if (cache == Os->cacheTail)
707 Os->cacheTail = cache->prev;
711 cache->next->prev = cache->prev;
716 #ifndef NO_DMA_COHERENT
718 *DmaHandle = cache->dmaHandle;
727 #ifndef NO_DMA_COHERENT
735 _FreeAllNonPagedMemoryCache(
739 gcsNonPagedMemoryCache *cache, *nextCache;
743 cache = Os->cacheHead;
745 while (cache != gcvNULL)
747 if (cache != Os->cacheTail)
749 nextCache = cache->next;
756 /* Remove the cache from list */
757 if (cache == Os->cacheHead)
759 Os->cacheHead = cache->next;
761 if (Os->cacheHead == gcvNULL)
763 Os->cacheTail = gcvNULL;
768 cache->prev->next = cache->next;
770 if (cache == Os->cacheTail)
772 Os->cacheTail = cache->prev;
776 cache->next->prev = cache->prev;
780 #ifndef NO_DMA_COHERENT
781 dma_free_coherent(gcvNULL,
786 free_pages((unsigned long)page_address(cache->page), cache->order);
797 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
799 /*******************************************************************************
800 ** Integer Id Management.
804 IN gcsINTEGER_DB_PTR Database,
805 IN gctPOINTER KernelPointer,
812 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
813 idr_preload(GFP_KERNEL | gcdNOWARN);
815 spin_lock(&Database->lock);
817 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
818 result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
822 Database->curr = *Id;
825 spin_unlock(&Database->lock);
831 return gcvSTATUS_OUT_OF_RESOURCES;
837 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
839 return gcvSTATUS_OUT_OF_MEMORY;
842 spin_lock(&Database->lock);
844 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
846 /* Try to get a id greater than current id. */
847 result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
851 Database->curr = *Id;
854 spin_unlock(&Database->lock);
856 if (result == -EAGAIN)
863 return gcvSTATUS_OUT_OF_RESOURCES;
872 IN gcsINTEGER_DB_PTR Database,
874 OUT gctPOINTER * KernelPointer
879 spin_lock(&Database->lock);
881 pointer = idr_find(&Database->idr, Id);
883 spin_unlock(&Database->lock);
887 *KernelPointer = pointer;
893 gcvLEVEL_ERROR, gcvZONE_OS,
894 "%s(%d) Id = %d is not found",
895 __FUNCTION__, __LINE__, Id);
897 return gcvSTATUS_NOT_FOUND;
903 IN gcsINTEGER_DB_PTR Database,
907 spin_lock(&Database->lock);
909 idr_remove(&Database->idr, Id);
911 spin_unlock(&Database->lock);
919 IN gctPOINTER Logical,
923 if (unlikely(current->mm == gcvNULL))
925 /* Do nothing if process is exiting. */
929 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
930 if (vm_munmap((unsigned long)Logical, Size) < 0)
933 gcvLEVEL_WARNING, gcvZONE_OS,
934 "%s(%d): vm_munmap failed",
935 __FUNCTION__, __LINE__
939 down_write(¤t->mm->mmap_sem);
940 if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
943 gcvLEVEL_WARNING, gcvZONE_OS,
944 "%s(%d): do_munmap failed",
945 __FUNCTION__, __LINE__
948 up_write(¤t->mm->mmap_sem);
953 _QueryProcessPageTable(
954 IN gctPOINTER Logical,
955 OUT gctUINT32 * Address
959 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
967 return gcvSTATUS_NOT_FOUND;
970 pgd = pgd_offset(current->mm, logical);
971 if (pgd_none(*pgd) || pgd_bad(*pgd))
973 return gcvSTATUS_NOT_FOUND;
976 pud = pud_offset(pgd, logical);
977 if (pud_none(*pud) || pud_bad(*pud))
979 return gcvSTATUS_NOT_FOUND;
982 pmd = pmd_offset(pud, logical);
983 if (pmd_none(*pmd) || pmd_bad(*pmd))
985 return gcvSTATUS_NOT_FOUND;
988 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
991 return gcvSTATUS_NOT_FOUND;
994 if (!pte_present(*pte))
996 pte_unmap_unlock(pte, lock);
997 return gcvSTATUS_NOT_FOUND;
1000 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
1001 pte_unmap_unlock(pte, lock);
1003 return gcvSTATUS_OK;
1006 /*******************************************************************************
1010 ** Construct a new gckOS object.
1014 ** gctPOINTER Context
1015 ** Pointer to the gckGALDEVICE class.
1020 ** Pointer to a variable that will hold the pointer to the gckOS object.
1024 IN gctPOINTER Context,
1031 gcmkHEADER_ARG("Context=0x%X", Context);
1033 /* Verify the arguments. */
1034 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
1036 /* Allocate the gckOS object. */
1037 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
1041 /* Out of memory. */
1042 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1043 return gcvSTATUS_OUT_OF_MEMORY;
1046 /* Zero the memory. */
1047 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
1049 /* Initialize the gckOS object. */
1050 os->object.type = gcvOBJ_OS;
1052 /* Set device device. */
1053 os->device = Context;
1055 /* IMPORTANT! No heap yet. */
1058 /* Initialize the memory lock. */
1059 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
1060 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
1062 /* Create debug lock mutex. */
1063 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
1066 os->mdlHead = os->mdlTail = gcvNULL;
1068 /* Get the kernel process ID. */
1069 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
1072 * Initialize the signal manager.
1075 /* Initialize mutex. */
1076 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
1078 /* Initialize signal id database lock. */
1079 spin_lock_init(&os->signalDB.lock);
1081 /* Initialize signal id database. */
1082 idr_init(&os->signalDB.idr);
1084 #if gcdANDROID_NATIVE_FENCE_SYNC
1086 * Initialize the sync point manager.
1089 /* Initialize mutex. */
1090 gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
1092 /* Initialize sync point id database lock. */
1093 spin_lock_init(&os->syncPointDB.lock);
1095 /* Initialize sync point id database. */
1096 idr_init(&os->syncPointDB.idr);
1099 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1101 os->cacheHead = gcvNULL;
1102 os->cacheTail = gcvNULL;
1105 /* Create a workqueue for os timer. */
1106 os->workqueue = create_singlethread_workqueue("galcore workqueue");
1108 if (os->workqueue == gcvNULL)
1110 /* Out of memory. */
1111 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1114 /* Return pointer to the gckOS object. */
1118 gcmkFOOTER_ARG("*Os=0x%X", *Os);
1119 return gcvSTATUS_OK;
1123 #if gcdANDROID_NATIVE_FENCE_SYNC
1124 if (os->syncPointMutex != gcvNULL)
1127 gckOS_DeleteMutex(os, os->syncPointMutex));
1131 if (os->signalMutex != gcvNULL)
1134 gckOS_DeleteMutex(os, os->signalMutex));
1137 if (os->heap != gcvNULL)
1140 gckHEAP_Destroy(os->heap));
1143 if (os->memoryMapLock != gcvNULL)
1146 gckOS_DeleteMutex(os, os->memoryMapLock));
1149 if (os->memoryLock != gcvNULL)
1152 gckOS_DeleteMutex(os, os->memoryLock));
1155 if (os->debugLock != gcvNULL)
1158 gckOS_DeleteMutex(os, os->debugLock));
1161 if (os->workqueue != gcvNULL)
1163 destroy_workqueue(os->workqueue);
1168 /* Return the error. */
1173 /*******************************************************************************
1177 ** Destroy an gckOS object.
1182 ** Pointer to an gckOS object that needs to be destroyed.
1195 gcmkHEADER_ARG("Os=0x%X", Os);
1197 /* Verify the arguments. */
1198 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1200 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1201 _FreeAllNonPagedMemoryCache(Os);
1204 #if gcdANDROID_NATIVE_FENCE_SYNC
1206 * Destroy the sync point manager.
1209 /* Destroy the mutex. */
1210 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
1214 * Destroy the signal manager.
1217 /* Destroy the mutex. */
1218 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
1220 if (Os->heap != gcvNULL)
1222 /* Mark gckHEAP as gone. */
1226 /* Destroy the gckHEAP object. */
1227 gcmkVERIFY_OK(gckHEAP_Destroy(heap));
1230 /* Destroy the memory lock. */
1231 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
1232 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
1234 /* Destroy debug lock mutex. */
1235 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
1237 /* Wait for all works done. */
1238 flush_workqueue(Os->workqueue);
1240 /* Destory work queue. */
1241 destroy_workqueue(Os->workqueue);
1243 /* Flush the debug cache. */
1244 gcmkDEBUGFLUSH(~0U);
1246 /* Mark the gckOS object as unknown. */
1247 Os->object.type = gcvOBJ_UNKNOWN;
1249 /* Free the gckOS object. */
1254 return gcvSTATUS_OK;
1258 _CreateKernelVirtualMapping(
1263 gctINT numPages = Mdl->numPages;
1265 #if gcdNONPAGED_MEMORY_CACHEABLE
1266 if (Mdl->contiguous)
1268 addr = page_address(Mdl->u.contiguousPages);
1272 addr = vmap(Mdl->u.nonContiguousPages,
1277 /* Trigger a page fault. */
1278 memset(addr, 0, numPages * PAGE_SIZE);
1281 struct page ** pages;
1282 gctBOOL free = gcvFALSE;
1285 if (Mdl->contiguous)
1287 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
1294 for (i = 0; i < numPages; i++)
1296 pages[i] = nth_page(Mdl->u.contiguousPages, i);
1303 pages = Mdl->u.nonContiguousPages;
1306 /* ioremap() can't work on system memory since 2.6.38. */
1307 addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
1309 /* Trigger a page fault. */
1310 memset(addr, 0, numPages * PAGE_SIZE);
1323 _DestoryKernelVirtualMapping(
1327 #if !gcdNONPAGED_MEMORY_CACHEABLE
1333 gckOS_CreateKernelVirtualMapping(
1334 IN gctPHYS_ADDR Physical,
1335 OUT gctSIZE_T * PageCount,
1336 OUT gctPOINTER * Logical
1339 *PageCount = ((PLINUX_MDL)Physical)->numPages;
1340 *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
1342 return gcvSTATUS_OK;
1346 gckOS_DestroyKernelVirtualMapping(
1347 IN gctPOINTER Logical
1350 _DestoryKernelVirtualMapping((gctSTRING)Logical);
1351 return gcvSTATUS_OK;
1354 /*******************************************************************************
1363 ** Pointer to an gckOS object.
1366 ** Number of bytes to allocate.
1370 ** gctPOINTER * Memory
1371 ** Pointer to a variable that will hold the allocated memory location.
1377 OUT gctPOINTER * Memory
1382 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1384 /* Verify the arguments. */
1385 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1386 gcmkVERIFY_ARGUMENT(Bytes > 0);
1387 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1389 /* Do we have a heap? */
1390 if (Os->heap != gcvNULL)
1392 /* Allocate from the heap. */
1393 gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
1397 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
1401 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1402 return gcvSTATUS_OK;
1405 /* Return the status. */
1410 /*******************************************************************************
1414 ** Free allocated memory.
1419 ** Pointer to an gckOS object.
1421 ** gctPOINTER Memory
1422 ** Pointer to memory allocation to free.
1431 IN gctPOINTER Memory
1436 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
1438 /* Verify the arguments. */
1439 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1440 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1442 /* Do we have a heap? */
1443 if (Os->heap != gcvNULL)
1445 /* Free from the heap. */
1446 gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
1450 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1455 return gcvSTATUS_OK;
1458 /* Return the status. */
1463 /*******************************************************************************
1465 ** gckOS_AllocateMemory
1467 ** Allocate memory wrapper.
1472 ** Number of bytes to allocate.
1476 ** gctPOINTER * Memory
1477 ** Pointer to a variable that will hold the allocated memory location.
1480 gckOS_AllocateMemory(
1483 OUT gctPOINTER * Memory
1489 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1491 /* Verify the arguments. */
1492 gcmkVERIFY_ARGUMENT(Bytes > 0);
1493 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1495 if (Bytes > PAGE_SIZE)
1497 memory = (gctPOINTER) vmalloc(Bytes);
1501 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1504 if (memory == gcvNULL)
1506 /* Out of memory. */
1507 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1510 /* Return pointer to the memory allocation. */
1514 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1515 return gcvSTATUS_OK;
1518 /* Return the status. */
1523 /*******************************************************************************
1527 ** Free allocated memory wrapper.
1531 ** gctPOINTER Memory
1532 ** Pointer to memory allocation to free.
1541 IN gctPOINTER Memory
1544 gcmkHEADER_ARG("Memory=0x%X", Memory);
1546 /* Verify the arguments. */
1547 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1549 /* Free the memory from the OS pool. */
1550 if (is_vmalloc_addr(Memory))
1561 return gcvSTATUS_OK;
1564 /*******************************************************************************
1568 ** Map physical memory into the current process.
1573 ** Pointer to an gckOS object.
1575 ** gctPHYS_ADDR Physical
1576 ** Start of physical address memory.
1579 ** Number of bytes to map.
1583 ** gctPOINTER * Memory
1584 ** Pointer to a variable that will hold the logical address of the
1590 IN gctPHYS_ADDR Physical,
1592 OUT gctPOINTER * Logical
1595 PLINUX_MDL_MAP mdlMap;
1596 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1598 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1600 /* Verify the arguments. */
1601 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1602 gcmkVERIFY_ARGUMENT(Physical != 0);
1603 gcmkVERIFY_ARGUMENT(Bytes > 0);
1604 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1608 mdlMap = FindMdlMap(mdl, _GetProcessID());
1610 if (mdlMap == gcvNULL)
1612 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1614 if (mdlMap == gcvNULL)
1618 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1619 return gcvSTATUS_OUT_OF_MEMORY;
1623 if (mdlMap->vmaAddr == gcvNULL)
1625 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1626 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1628 mdl->numPages * PAGE_SIZE,
1629 PROT_READ | PROT_WRITE,
1633 down_write(¤t->mm->mmap_sem);
1635 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1637 mdl->numPages * PAGE_SIZE,
1638 PROT_READ | PROT_WRITE,
1642 up_write(¤t->mm->mmap_sem);
1645 if (IS_ERR(mdlMap->vmaAddr))
1649 "%s(%d): do_mmap_pgoff error",
1650 __FUNCTION__, __LINE__
1655 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1656 __FUNCTION__, __LINE__,
1661 mdlMap->vmaAddr = gcvNULL;
1665 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1666 return gcvSTATUS_OUT_OF_MEMORY;
1669 down_write(¤t->mm->mmap_sem);
1671 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1677 "%s(%d): find_vma error.",
1678 __FUNCTION__, __LINE__
1681 mdlMap->vmaAddr = gcvNULL;
1683 up_write(¤t->mm->mmap_sem);
1687 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1688 return gcvSTATUS_OUT_OF_RESOURCES;
1691 #ifndef NO_DMA_COHERENT
1692 if (dma_mmap_coherent(gcvNULL,
1696 mdl->numPages * PAGE_SIZE) < 0)
1698 up_write(¤t->mm->mmap_sem);
1702 "%s(%d): dma_mmap_coherent error.",
1703 __FUNCTION__, __LINE__
1706 mdlMap->vmaAddr = gcvNULL;
1710 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1711 return gcvSTATUS_OUT_OF_RESOURCES;
1714 #if !gcdPAGED_MEMORY_CACHEABLE
1715 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1716 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1718 mdlMap->vma->vm_pgoff = 0;
1720 if (remap_pfn_range(mdlMap->vma,
1721 mdlMap->vma->vm_start,
1722 mdl->dmaHandle >> PAGE_SHIFT,
1723 mdl->numPages*PAGE_SIZE,
1724 mdlMap->vma->vm_page_prot) < 0)
1726 up_write(¤t->mm->mmap_sem);
1730 "%s(%d): remap_pfn_range error.",
1731 __FUNCTION__, __LINE__
1734 mdlMap->vmaAddr = gcvNULL;
1738 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1739 return gcvSTATUS_OUT_OF_RESOURCES;
1743 up_write(¤t->mm->mmap_sem);
1748 *Logical = mdlMap->vmaAddr;
1750 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1751 return gcvSTATUS_OK;
1754 /*******************************************************************************
1756 ** gckOS_UnmapMemory
1758 ** Unmap physical memory out of the current process.
1763 ** Pointer to an gckOS object.
1765 ** gctPHYS_ADDR Physical
1766 ** Start of physical address memory.
1769 ** Number of bytes to unmap.
1771 ** gctPOINTER Memory
1772 ** Pointer to a previously mapped memory region.
1781 IN gctPHYS_ADDR Physical,
1783 IN gctPOINTER Logical
1786 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1787 Os, Physical, Bytes, Logical);
1789 /* Verify the arguments. */
1790 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1791 gcmkVERIFY_ARGUMENT(Physical != 0);
1792 gcmkVERIFY_ARGUMENT(Bytes > 0);
1793 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1795 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1799 return gcvSTATUS_OK;
1803 /*******************************************************************************
1805 ** gckOS_UnmapMemoryEx
1807 ** Unmap physical memory in the specified process.
1812 ** Pointer to an gckOS object.
1814 ** gctPHYS_ADDR Physical
1815 ** Start of physical address memory.
1818 ** Number of bytes to unmap.
1820 ** gctPOINTER Memory
1821 ** Pointer to a previously mapped memory region.
1824 ** Pid of the process that opened the device and mapped this memory.
1831 gckOS_UnmapMemoryEx(
1833 IN gctPHYS_ADDR Physical,
1835 IN gctPOINTER Logical,
1839 PLINUX_MDL_MAP mdlMap;
1840 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1842 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1843 Os, Physical, Bytes, Logical, PID);
1845 /* Verify the arguments. */
1846 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1847 gcmkVERIFY_ARGUMENT(Physical != 0);
1848 gcmkVERIFY_ARGUMENT(Bytes > 0);
1849 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1850 gcmkVERIFY_ARGUMENT(PID != 0);
1856 mdlMap = FindMdlMap(mdl, PID);
1858 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1862 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1863 return gcvSTATUS_INVALID_ARGUMENT;
1866 _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1868 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1875 return gcvSTATUS_OK;
1878 /*******************************************************************************
1880 ** gckOS_UnmapUserLogical
1882 ** Unmap user logical memory out of physical memory.
1887 ** Pointer to an gckOS object.
1889 ** gctPHYS_ADDR Physical
1890 ** Start of physical address memory.
1893 ** Number of bytes to unmap.
1895 ** gctPOINTER Memory
1896 ** Pointer to a previously mapped memory region.
1903 gckOS_UnmapUserLogical(
1905 IN gctPHYS_ADDR Physical,
1907 IN gctPOINTER Logical
1910 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1911 Os, Physical, Bytes, Logical);
1913 /* Verify the arguments. */
1914 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1915 gcmkVERIFY_ARGUMENT(Physical != 0);
1916 gcmkVERIFY_ARGUMENT(Bytes > 0);
1917 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1919 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1923 return gcvSTATUS_OK;
1927 /*******************************************************************************
1929 ** gckOS_AllocateNonPagedMemory
1931 ** Allocate a number of pages from non-paged memory.
1936 ** Pointer to an gckOS object.
1938 ** gctBOOL InUserSpace
1939 ** gcvTRUE if the pages need to be mapped into user space.
1941 ** gctSIZE_T * Bytes
1942 ** Pointer to a variable that holds the number of bytes to allocate.
1946 ** gctSIZE_T * Bytes
1947 ** Pointer to a variable that hold the number of bytes allocated.
1949 ** gctPHYS_ADDR * Physical
1950 ** Pointer to a variable that will hold the physical address of the
1953 ** gctPOINTER * Logical
1954 ** Pointer to a variable that will hold the logical address of the
1958 gckOS_AllocateNonPagedMemory(
1960 IN gctBOOL InUserSpace,
1961 IN OUT gctSIZE_T * Bytes,
1962 OUT gctPHYS_ADDR * Physical,
1963 OUT gctPOINTER * Logical
1968 PLINUX_MDL mdl = gcvNULL;
1969 PLINUX_MDL_MAP mdlMap = gcvNULL;
1971 #ifdef NO_DMA_COHERENT
1976 gctBOOL locked = gcvFALSE;
1979 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1980 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1982 /* Verify the arguments. */
1983 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1984 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1985 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1986 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1987 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1989 /* Align number of bytes to page size. */
1990 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1992 /* Get total number of pages.. */
1993 numPages = GetPageCount(bytes, 0);
1995 /* Allocate mdl+vector structure */
1996 mdl = _CreateMdl(_GetProcessID());
1999 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2003 mdl->numPages = numPages;
2008 #ifndef NO_DMA_COHERENT
2009 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2010 addr = _GetNonPagedMemoryCache(Os,
2011 mdl->numPages * PAGE_SIZE,
2014 if (addr == gcvNULL)
2017 addr = dma_alloc_coherent(gcvNULL,
2018 mdl->numPages * PAGE_SIZE,
2020 GFP_KERNEL | gcdNOWARN);
2023 size = mdl->numPages * PAGE_SIZE;
2024 order = get_order(size);
2025 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2026 page = _GetNonPagedMemoryCache(Os, order);
2028 if (page == gcvNULL)
2031 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
2034 if (page == gcvNULL)
2036 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2039 vaddr = (gctPOINTER)page_address(page);
2040 mdl->contiguous = gcvTRUE;
2041 mdl->u.contiguousPages = page;
2042 addr = _CreateKernelVirtualMapping(mdl);
2043 mdl->dmaHandle = virt_to_phys(vaddr);
2045 mdl->u.contiguousPages = page;
2047 #if !defined(CONFIG_PPC)
2048 /* Cache invalidate. */
2049 dma_sync_single_for_device(
2058 SetPageReserved(virt_to_page(vaddr));
2065 if (addr == gcvNULL)
2067 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2072 /* Return allocated memory. */
2074 *Physical = (gctPHYS_ADDR) mdl;
2078 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
2080 if (mdlMap == gcvNULL)
2082 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2085 /* Only after mmap this will be valid. */
2087 /* We need to map this to user space. */
2088 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2089 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
2091 mdl->numPages * PAGE_SIZE,
2092 PROT_READ | PROT_WRITE,
2096 down_write(¤t->mm->mmap_sem);
2098 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
2100 mdl->numPages * PAGE_SIZE,
2101 PROT_READ | PROT_WRITE,
2105 up_write(¤t->mm->mmap_sem);
2108 if (IS_ERR(mdlMap->vmaAddr))
2111 gcvLEVEL_WARNING, gcvZONE_OS,
2112 "%s(%d): do_mmap_pgoff error",
2113 __FUNCTION__, __LINE__
2116 mdlMap->vmaAddr = gcvNULL;
2118 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2121 down_write(¤t->mm->mmap_sem);
2123 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
2125 if (mdlMap->vma == gcvNULL)
2128 gcvLEVEL_WARNING, gcvZONE_OS,
2129 "%s(%d): find_vma error",
2130 __FUNCTION__, __LINE__
2133 up_write(¤t->mm->mmap_sem);
2135 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2138 #ifndef NO_DMA_COHERENT
2139 if (dma_mmap_coherent(gcvNULL,
2143 mdl->numPages * PAGE_SIZE) < 0)
2146 gcvLEVEL_WARNING, gcvZONE_OS,
2147 "%s(%d): dma_mmap_coherent error",
2148 __FUNCTION__, __LINE__
2151 up_write(¤t->mm->mmap_sem);
2153 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2156 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
2157 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
2158 mdlMap->vma->vm_pgoff = 0;
2160 if (remap_pfn_range(mdlMap->vma,
2161 mdlMap->vma->vm_start,
2162 mdl->dmaHandle >> PAGE_SHIFT,
2163 mdl->numPages * PAGE_SIZE,
2164 mdlMap->vma->vm_page_prot))
2167 gcvLEVEL_WARNING, gcvZONE_OS,
2168 "%s(%d): remap_pfn_range error",
2169 __FUNCTION__, __LINE__
2172 up_write(¤t->mm->mmap_sem);
2174 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2176 #endif /* NO_DMA_COHERENT */
2178 up_write(¤t->mm->mmap_sem);
2180 *Logical = mdlMap->vmaAddr;
2184 *Logical = (gctPOINTER)mdl->addr;
2188 * Add this to a global list.
2189 * Will be used by get physical address
2190 * and mapuser pointer functions.
2195 /* Initialize the queue. */
2196 Os->mdlHead = Os->mdlTail = mdl;
2200 /* Add to the tail. */
2201 mdl->prev = Os->mdlTail;
2202 Os->mdlTail->next = mdl;
2209 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
2210 *Bytes, *Physical, *Logical);
2211 return gcvSTATUS_OK;
2214 if (mdlMap != gcvNULL)
2216 /* Free LINUX_MDL_MAP. */
2217 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
2222 /* Free LINUX_MDL. */
2223 gcmkVERIFY_OK(_DestroyMdl(mdl));
2228 /* Unlock memory. */
2232 /* Return the status. */
2237 /*******************************************************************************
2239 ** gckOS_FreeNonPagedMemory
2241 ** Free previously allocated and mapped pages from non-paged memory.
2246 ** Pointer to an gckOS object.
2249 ** Number of bytes allocated.
2251 ** gctPHYS_ADDR Physical
2252 ** Physical address of the allocated memory.
2254 ** gctPOINTER Logical
2255 ** Logical address of the allocated memory.
2261 gceSTATUS gckOS_FreeNonPagedMemory(
2264 IN gctPHYS_ADDR Physical,
2265 IN gctPOINTER Logical
2269 PLINUX_MDL_MAP mdlMap;
2270 #ifdef NO_DMA_COHERENT
2273 #endif /* NO_DMA_COHERENT */
2275 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
2276 Os, Bytes, Physical, Logical);
2278 /* Verify the arguments. */
2279 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2280 gcmkVERIFY_ARGUMENT(Bytes > 0);
2281 gcmkVERIFY_ARGUMENT(Physical != 0);
2282 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2284 /* Convert physical address into a pointer to a MDL. */
2285 mdl = (PLINUX_MDL) Physical;
2289 #ifndef NO_DMA_COHERENT
2290 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2291 if (!_AddNonPagedMemoryCache(Os,
2292 mdl->numPages * PAGE_SIZE,
2297 dma_free_coherent(gcvNULL,
2298 mdl->numPages * PAGE_SIZE,
2303 size = mdl->numPages * PAGE_SIZE;
2308 ClearPageReserved(virt_to_page(vaddr));
2314 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2315 if (!_AddNonPagedMemoryCache(Os,
2316 get_order(mdl->numPages * PAGE_SIZE),
2317 virt_to_page(mdl->kaddr)))
2320 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
2323 _DestoryKernelVirtualMapping(mdl->addr);
2324 #endif /* NO_DMA_COHERENT */
2328 while (mdlMap != gcvNULL)
2330 if (mdlMap->vmaAddr != gcvNULL)
2332 /* No mapped memory exists when free nonpaged memory */
2336 mdlMap = mdlMap->next;
2339 /* Remove the node from global list.. */
2340 if (mdl == Os->mdlHead)
2342 if ((Os->mdlHead = mdl->next) == gcvNULL)
2344 Os->mdlTail = gcvNULL;
2349 mdl->prev->next = mdl->next;
2350 if (mdl == Os->mdlTail)
2352 Os->mdlTail = mdl->prev;
2356 mdl->next->prev = mdl->prev;
2362 gcmkVERIFY_OK(_DestroyMdl(mdl));
2366 return gcvSTATUS_OK;
2369 /*******************************************************************************
2371 ** gckOS_ReadRegister
2373 ** Read data from a register.
2378 ** Pointer to an gckOS object.
2380 ** gctUINT32 Address
2381 ** Address of register.
2386 ** Pointer to a variable that receives the data read from the register.
2391 IN gctUINT32 Address,
2392 OUT gctUINT32 * Data
2395 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2399 gckOS_ReadRegisterEx(
2402 IN gctUINT32 Address,
2403 OUT gctUINT32 * Data
2406 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
2408 /* Verify the arguments. */
2409 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2410 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2411 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2413 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
2416 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2417 return gcvSTATUS_OK;
2420 /*******************************************************************************
2422 ** gckOS_WriteRegister
2424 ** Write data to a register.
2429 ** Pointer to an gckOS object.
2431 ** gctUINT32 Address
2432 ** Address of register.
2435 ** Data for register.
2442 gckOS_WriteRegister(
2444 IN gctUINT32 Address,
2448 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2452 gckOS_WriteRegisterEx(
2455 IN gctUINT32 Address,
2459 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2461 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2463 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2467 return gcvSTATUS_OK;
2470 /*******************************************************************************
2472 ** gckOS_GetPageSize
2474 ** Get the system's page size.
2479 ** Pointer to an gckOS object.
2483 ** gctSIZE_T * PageSize
2484 ** Pointer to a variable that will receive the system's page size.
2486 gceSTATUS gckOS_GetPageSize(
2488 OUT gctSIZE_T * PageSize
2491 gcmkHEADER_ARG("Os=0x%X", Os);
2493 /* Verify the arguments. */
2494 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2495 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2497 /* Return the page size. */
2498 *PageSize = (gctSIZE_T) PAGE_SIZE;
2501 gcmkFOOTER_ARG("*PageSize", *PageSize);
2502 return gcvSTATUS_OK;
2505 /*******************************************************************************
2507 ** gckOS_GetPhysicalAddress
2509 ** Get the physical system address of a corresponding virtual address.
2514 ** Pointer to an gckOS object.
2516 ** gctPOINTER Logical
2521 ** gctUINT32 * Address
2522 ** Poinetr to a variable that receives the 32-bit physical adress.
2525 gckOS_GetPhysicalAddress(
2527 IN gctPOINTER Logical,
2528 OUT gctUINT32 * Address
2532 gctUINT32 processID;
2534 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2536 /* Verify the arguments. */
2537 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2538 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2540 /* Query page table of current process first. */
2541 status = _QueryProcessPageTable(Logical, Address);
2543 if (gcmIS_ERROR(status))
2545 /* Get current process ID. */
2546 processID = _GetProcessID();
2548 /* Route through other function. */
2550 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2554 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2555 return gcvSTATUS_OK;
2558 /* Return the status. */
2567 IN gctUINT32 Physical,
2568 IN gctPOINTER Logical,
2573 gcsUSER_MAPPING_PTR map;
2575 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2576 Os, Physical, Logical, Bytes);
2578 gcmkONERROR(gckOS_Allocate(Os,
2579 gcmSIZEOF(gcsUSER_MAPPING),
2580 (gctPOINTER *) &map));
2582 map->next = Os->userMap;
2583 map->physical = Physical - Os->device->baseAddress;
2584 map->logical = Logical;
2586 map->start = (gctINT8_PTR) Logical;
2587 map->end = map->start + Bytes;
2592 return gcvSTATUS_OK;
2600 gckOS_RemoveMapping(
2602 IN gctPOINTER Logical,
2607 gcsUSER_MAPPING_PTR map, prev;
2609 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2611 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2613 if ((map->logical == Logical)
2614 && (map->bytes == Bytes)
2625 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2628 if (prev == gcvNULL)
2630 Os->userMap = map->next;
2634 prev->next = map->next;
2637 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2640 return gcvSTATUS_OK;
2649 _ConvertLogical2Physical(
2651 IN gctPOINTER Logical,
2652 IN gctUINT32 ProcessID,
2654 OUT gctUINT32_PTR Physical
2657 gctINT8_PTR base, vBase;
2660 gcsUSER_MAPPING_PTR userMap;
2662 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2664 /* Check for the logical address match. */
2665 if ((base != gcvNULL)
2666 && ((gctINT8_PTR) Logical >= base)
2667 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2670 offset = (gctINT8_PTR) Logical - base;
2672 if (Mdl->dmaHandle != 0)
2674 /* The memory was from coherent area. */
2675 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2677 else if (Mdl->pagedMem && !Mdl->contiguous)
2679 /* paged memory is not mapped to kernel space. */
2680 return gcvSTATUS_INVALID_ADDRESS;
2684 *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
2687 return gcvSTATUS_OK;
2690 /* Walk user maps. */
2691 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2693 if (((gctINT8_PTR) Logical >= userMap->start)
2694 && ((gctINT8_PTR) Logical < userMap->end)
2697 *Physical = userMap->physical
2698 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2700 return gcvSTATUS_OK;
2704 if (ProcessID != Os->kernelProcessID)
2706 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2707 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2709 /* Is the given address within that range. */
2710 if ((vBase != gcvNULL)
2711 && ((gctINT8_PTR) Logical >= vBase)
2712 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2715 offset = (gctINT8_PTR) Logical - vBase;
2717 if (Mdl->dmaHandle != 0)
2719 /* The memory was from coherent area. */
2720 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2722 else if (Mdl->pagedMem && !Mdl->contiguous)
2724 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2728 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2731 return gcvSTATUS_OK;
2735 /* Address not yet found. */
2736 return gcvSTATUS_INVALID_ADDRESS;
2739 /*******************************************************************************
2741 ** gckOS_GetPhysicalAddressProcess
2743 ** Get the physical system address of a corresponding virtual address for a
2749 ** Pointer to gckOS object.
2751 ** gctPOINTER Logical
2754 ** gctUINT32 ProcessID
2759 ** gctUINT32 * Address
2760 ** Poinetr to a variable that receives the 32-bit physical adress.
2763 gckOS_GetPhysicalAddressProcess(
2765 IN gctPOINTER Logical,
2766 IN gctUINT32 ProcessID,
2767 OUT gctUINT32 * Address
2772 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2774 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2776 /* Verify the arguments. */
2777 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2778 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2782 /* First try the contiguous memory pool. */
2783 if (Os->device->contiguousMapped)
2785 base = (gctINT8_PTR) Os->device->contiguousBase;
2787 if (((gctINT8_PTR) Logical >= base)
2788 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2791 /* Convert logical address into physical. */
2792 *Address = Os->device->contiguousVidMem->baseAddress
2793 + (gctINT8_PTR) Logical - base;
2794 status = gcvSTATUS_OK;
2799 /* Try the contiguous memory pool. */
2800 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2801 status = _ConvertLogical2Physical(Os,
2808 if (gcmIS_ERROR(status))
2810 /* Walk all MDLs. */
2811 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2814 status = _ConvertLogical2Physical(Os,
2819 if (gcmIS_SUCCESS(status))
2828 gcmkONERROR(status);
2831 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2832 return gcvSTATUS_OK;
2835 /* Return the status. */
2840 /*******************************************************************************
2842 ** gckOS_MapPhysical
2844 ** Map a physical address into kernel space.
2849 ** Pointer to an gckOS object.
2851 ** gctUINT32 Physical
2852 ** Physical address of the memory to map.
2855 ** Number of bytes to map.
2859 ** gctPOINTER * Logical
2860 ** Pointer to a variable that receives the base address of the mapped
2866 IN gctUINT32 Physical,
2868 OUT gctPOINTER * Logical
2873 gctUINT32 physical = Physical;
2875 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2877 /* Verify the arguments. */
2878 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2879 gcmkVERIFY_ARGUMENT(Bytes > 0);
2880 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2884 /* Go through our mapping to see if we know this physical address already. */
2887 while (mdl != gcvNULL)
2889 if (mdl->dmaHandle != 0)
2891 if ((physical >= mdl->dmaHandle)
2892 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2895 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2905 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2906 struct contiguous_mem_pool *pool = Os->device->pool;
2908 if (Physical >= pool->phys && Physical < pool->phys + pool->size)
2909 logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
2913 /* Map memory as cached memory. */
2914 request_mem_region(physical, Bytes, "MapRegion");
2915 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2918 if (logical == gcvNULL)
2921 gcvLEVEL_INFO, gcvZONE_OS,
2922 "%s(%d): Failed to map physical address 0x%08x",
2923 __FUNCTION__, __LINE__, Physical
2928 /* Out of resources. */
2929 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2930 return gcvSTATUS_OUT_OF_RESOURCES;
2933 /* Return pointer to mapped memory. */
2940 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2941 return gcvSTATUS_OK;
2944 /*******************************************************************************
2946 ** gckOS_UnmapPhysical
2948 ** Unmap a previously mapped memory region from kernel memory.
2953 ** Pointer to an gckOS object.
2955 ** gctPOINTER Logical
2956 ** Pointer to the base address of the memory to unmap.
2959 ** Number of bytes to unmap.
2966 gckOS_UnmapPhysical(
2968 IN gctPOINTER Logical,
2974 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2976 /* Verify the arguments. */
2977 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2978 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2979 gcmkVERIFY_ARGUMENT(Bytes > 0);
2985 while (mdl != gcvNULL)
2987 if (mdl->addr != gcvNULL)
2989 if (Logical >= (gctPOINTER)mdl->addr
2990 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
3001 /* Unmap the memory. */
3009 return gcvSTATUS_OK;
3012 /*******************************************************************************
3014 ** gckOS_CreateMutex
3016 ** Create a new mutex.
3021 ** Pointer to an gckOS object.
3025 ** gctPOINTER * Mutex
3026 ** Pointer to a variable that will hold a pointer to the mutex.
3031 OUT gctPOINTER * Mutex
3036 gcmkHEADER_ARG("Os=0x%X", Os);
3038 /* Validate the arguments. */
3039 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3040 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3042 /* Allocate the mutex structure. */
3043 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
3045 /* Initialize the mutex. */
3048 /* Return status. */
3049 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
3050 return gcvSTATUS_OK;
3053 /* Return status. */
3058 /*******************************************************************************
3060 ** gckOS_DeleteMutex
3067 ** Pointer to an gckOS object.
3070 ** Pointer to the mute to be deleted.
3084 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
3086 /* Validate the arguments. */
3087 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3088 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3090 /* Destroy the mutex. */
3091 mutex_destroy(Mutex);
3093 /* Free the mutex structure. */
3094 gcmkONERROR(gckOS_Free(Os, Mutex));
3097 return gcvSTATUS_OK;
3100 /* Return status. */
3105 /*******************************************************************************
3107 ** gckOS_AcquireMutex
3114 ** Pointer to an gckOS object.
3117 ** Pointer to the mutex to be acquired.
3119 ** gctUINT32 Timeout
3120 ** Timeout value specified in milliseconds.
3121 ** Specify the value of gcvINFINITE to keep the thread suspended
3122 ** until the mutex has been acquired.
3131 IN gctPOINTER Mutex,
3132 IN gctUINT32 Timeout
3135 #if gcdDETECT_TIMEOUT
3139 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
3141 /* Validate the arguments. */
3142 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3143 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3145 #if gcdDETECT_TIMEOUT
3150 /* Try to acquire the mutex. */
3151 if (mutex_trylock(Mutex))
3155 return gcvSTATUS_OK;
3158 /* Advance the timeout. */
3161 if (Timeout == gcvINFINITE)
3163 if (timeout == gcdINFINITE_TIMEOUT)
3165 gctUINT32 dmaAddress1, dmaAddress2;
3166 gctUINT32 dmaState1, dmaState2;
3168 dmaState1 = dmaState2 =
3169 dmaAddress1 = dmaAddress2 = 0;
3171 /* Verify whether DMA is running. */
3172 gcmkVERIFY_OK(_VerifyDMA(
3173 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
3176 #if gcdDETECT_DMA_ADDRESS
3177 /* Dump only if DMA appears stuck. */
3179 (dmaAddress1 == dmaAddress2)
3180 #if gcdDETECT_DMA_STATE
3181 && (dmaState1 == dmaState2)
3186 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
3189 "%s(%d): mutex 0x%X; forced message flush.",
3190 __FUNCTION__, __LINE__, Mutex
3193 /* Flush the debug cache. */
3194 gcmkDEBUGFLUSH(dmaAddress2);
3203 if (timeout >= Timeout)
3209 /* Wait for 1 millisecond. */
3210 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3213 if (Timeout == gcvINFINITE)
3215 /* Lock the mutex. */
3220 return gcvSTATUS_OK;
3225 /* Try to acquire the mutex. */
3226 if (mutex_trylock(Mutex))
3230 return gcvSTATUS_OK;
3238 /* Wait for 1 millisecond. */
3239 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3244 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
3245 return gcvSTATUS_TIMEOUT;
3248 /*******************************************************************************
3250 ** gckOS_ReleaseMutex
3252 ** Release an acquired mutex.
3257 ** Pointer to an gckOS object.
3260 ** Pointer to the mutex to be released.
3272 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
3274 /* Validate the arguments. */
3275 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3276 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3278 /* Release the mutex. */
3279 mutex_unlock(Mutex);
3283 return gcvSTATUS_OK;
3286 /*******************************************************************************
3288 ** gckOS_AtomicExchange
3290 ** Atomically exchange a pair of 32-bit values.
3295 ** Pointer to an gckOS object.
3297 ** IN OUT gctINT32_PTR Target
3298 ** Pointer to the 32-bit value to exchange.
3300 ** IN gctINT32 NewValue
3301 ** Specifies a new value for the 32-bit value pointed to by Target.
3303 ** OUT gctINT32_PTR OldValue
3304 ** The old value of the 32-bit value pointed to by Target.
3311 gckOS_AtomicExchange(
3313 IN OUT gctUINT32_PTR Target,
3314 IN gctUINT32 NewValue,
3315 OUT gctUINT32_PTR OldValue
3318 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
3320 /* Verify the arguments. */
3321 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3323 /* Exchange the pair of 32-bit values. */
3324 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
3327 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
3328 return gcvSTATUS_OK;
3331 /*******************************************************************************
3333 ** gckOS_AtomicExchangePtr
3335 ** Atomically exchange a pair of pointers.
3340 ** Pointer to an gckOS object.
3342 ** IN OUT gctPOINTER * Target
3343 ** Pointer to the 32-bit value to exchange.
3345 ** IN gctPOINTER NewValue
3346 ** Specifies a new value for the pointer pointed to by Target.
3348 ** OUT gctPOINTER * OldValue
3349 ** The old value of the pointer pointed to by Target.
3356 gckOS_AtomicExchangePtr(
3358 IN OUT gctPOINTER * Target,
3359 IN gctPOINTER NewValue,
3360 OUT gctPOINTER * OldValue
3363 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3365 /* Verify the arguments. */
3366 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3368 /* Exchange the pair of pointers. */
3369 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3372 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3373 return gcvSTATUS_OK;
3377 /*******************************************************************************
3379 ** gckOS_AtomicSetMask
3381 ** Atomically set mask to Atom
3384 ** IN OUT gctPOINTER Atom
3385 ** Pointer to the atom to set.
3387 ** IN gctUINT32 Mask
3400 gctUINT32 oval, nval;
3402 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3403 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3407 oval = atomic_read((atomic_t *) Atom);
3409 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3412 return gcvSTATUS_OK;
3415 /*******************************************************************************
3417 ** gckOS_AtomClearMask
3419 ** Atomically clear mask from Atom
3422 ** IN OUT gctPOINTER Atom
3423 ** Pointer to the atom to clear.
3425 ** IN gctUINT32 Mask
3433 gckOS_AtomClearMask(
3438 gctUINT32 oval, nval;
3440 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3441 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3445 oval = atomic_read((atomic_t *) Atom);
3446 nval = oval & ~Mask;
3447 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3450 return gcvSTATUS_OK;
3454 /*******************************************************************************
3456 ** gckOS_AtomConstruct
3463 ** Pointer to a gckOS object.
3467 ** gctPOINTER * Atom
3468 ** Pointer to a variable receiving the constructed atom.
3471 gckOS_AtomConstruct(
3473 OUT gctPOINTER * Atom
3478 gcmkHEADER_ARG("Os=0x%X", Os);
3480 /* Verify the arguments. */
3481 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3482 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3484 /* Allocate the atom. */
3485 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3487 /* Initialize the atom. */
3488 atomic_set((atomic_t *) *Atom, 0);
3491 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3492 return gcvSTATUS_OK;
3495 /* Return the status. */
3500 /*******************************************************************************
3502 ** gckOS_AtomDestroy
3509 ** Pointer to a gckOS object.
3512 ** Pointer to the atom to destroy.
3526 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3528 /* Verify the arguments. */
3529 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3530 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3532 /* Free the atom. */
3533 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3537 return gcvSTATUS_OK;
3540 /* Return the status. */
3545 /*******************************************************************************
3549 ** Get the 32-bit value protected by an atom.
3554 ** Pointer to a gckOS object.
3557 ** Pointer to the atom.
3561 ** gctINT32_PTR Value
3562 ** Pointer to a variable the receives the value of the atom.
3568 OUT gctINT32_PTR Value
3571 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3573 /* Verify the arguments. */
3574 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3575 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3577 /* Return the current value of atom. */
3578 *Value = atomic_read((atomic_t *) Atom);
3581 gcmkFOOTER_ARG("*Value=%d", *Value);
3582 return gcvSTATUS_OK;
3585 /*******************************************************************************
3589 ** Set the 32-bit value protected by an atom.
3594 ** Pointer to a gckOS object.
3597 ** Pointer to the atom.
3600 ** The value of the atom.
3613 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3615 /* Verify the arguments. */
3616 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3617 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3619 /* Set the current value of atom. */
3620 atomic_set((atomic_t *) Atom, Value);
3624 return gcvSTATUS_OK;
3627 /*******************************************************************************
3629 ** gckOS_AtomIncrement
3631 ** Atomically increment the 32-bit integer value inside an atom.
3636 ** Pointer to a gckOS object.
3639 ** Pointer to the atom.
3643 ** gctINT32_PTR Value
3644 ** Pointer to a variable that receives the original value of the atom.
3647 gckOS_AtomIncrement(
3650 OUT gctINT32_PTR Value
3653 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3655 /* Verify the arguments. */
3656 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3657 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3659 /* Increment the atom. */
3660 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3663 gcmkFOOTER_ARG("*Value=%d", *Value);
3664 return gcvSTATUS_OK;
3667 /*******************************************************************************
3669 ** gckOS_AtomDecrement
3671 ** Atomically decrement the 32-bit integer value inside an atom.
3676 ** Pointer to a gckOS object.
3679 ** Pointer to the atom.
3683 ** gctINT32_PTR Value
3684 ** Pointer to a variable that receives the original value of the atom.
3687 gckOS_AtomDecrement(
3690 OUT gctINT32_PTR Value
3693 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3695 /* Verify the arguments. */
3696 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3697 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3699 /* Decrement the atom. */
3700 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3703 gcmkFOOTER_ARG("*Value=%d", *Value);
3704 return gcvSTATUS_OK;
3707 /*******************************************************************************
3711 ** Delay execution of the current thread for a number of milliseconds.
3716 ** Pointer to an gckOS object.
3719 ** Delay to sleep, specified in milliseconds.
3731 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3735 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3736 ktime_t delay = ktime_set(Delay/1000, (Delay%1000) * NSEC_PER_MSEC);
3737 __set_current_state(TASK_UNINTERRUPTIBLE);
3738 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3747 return gcvSTATUS_OK;
3750 /*******************************************************************************
3754 ** Get the number of milliseconds since the system started.
3760 ** gctUINT32_PTR Time
3761 ** Pointer to a variable to get time.
3766 OUT gctUINT32_PTR Time
3771 *Time = jiffies_to_msecs(jiffies);
3774 return gcvSTATUS_OK;
3777 /*******************************************************************************
3781 ** Compare time values got from gckOS_GetTicks.
3785 ** First time value to be compared.
3788 ** Second time value to be compared.
3792 ** gctBOOL_PTR IsAfter
3793 ** Pointer to a variable to result.
3800 OUT gctBOOL_PTR IsAfter
3805 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3808 return gcvSTATUS_OK;
3811 /*******************************************************************************
3815 ** Get the number of microseconds since the system started.
3821 ** gctUINT64_PTR Time
3822 ** Pointer to a variable to get time.
3827 OUT gctUINT64_PTR Time
3835 return gcvSTATUS_OK;
3838 /*******************************************************************************
3840 ** gckOS_MemoryBarrier
3842 ** Make sure the CPU has executed everything up to this point and the data got
3843 ** written to the specified pointer.
3848 ** Pointer to an gckOS object.
3850 ** gctPOINTER Address
3851 ** Address of memory that needs to be barriered.
3858 gckOS_MemoryBarrier(
3860 IN gctPOINTER Address
3863 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3865 /* Verify the arguments. */
3866 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3868 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3869 && defined (CONFIG_ARM) \
3870 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3871 /* drain write buffer */
3874 /* drain outer cache's write buffer? */
3881 return gcvSTATUS_OK;
3884 /*******************************************************************************
3886 ** gckOS_AllocatePagedMemory
3888 ** Allocate memory from the paged pool.
3893 ** Pointer to an gckOS object.
3896 ** Number of bytes to allocate.
3900 ** gctPHYS_ADDR * Physical
3901 ** Pointer to a variable that receives the physical address of the
3902 ** memory allocation.
3905 gckOS_AllocatePagedMemory(
3908 OUT gctPHYS_ADDR * Physical
3913 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3915 /* Verify the arguments. */
3916 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3917 gcmkVERIFY_ARGUMENT(Bytes > 0);
3918 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3920 /* Allocate the memory. */
3921 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
3924 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3925 return gcvSTATUS_OK;
3928 /* Return the status. */
3933 /*******************************************************************************
3935 ** gckOS_AllocatePagedMemoryEx
3937 ** Allocate memory from the paged pool.
3942 ** Pointer to an gckOS object.
3944 ** gctBOOL Contiguous
3945 ** Need contiguous memory or not.
3948 ** Number of bytes to allocate.
3952 ** gctPHYS_ADDR * Physical
3953 ** Pointer to a variable that receives the physical address of the
3954 ** memory allocation.
3957 gckOS_AllocatePagedMemoryEx(
3959 IN gctBOOL Contiguous,
3961 OUT gctPHYS_ADDR * Physical
3966 PLINUX_MDL mdl = gcvNULL;
3968 gctBOOL locked = gcvFALSE;
3970 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3971 gctPOINTER addr = gcvNULL;
3974 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
3976 /* Verify the arguments. */
3977 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3978 gcmkVERIFY_ARGUMENT(Bytes > 0);
3979 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3981 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3983 numPages = GetPageCount(bytes, 0);
3988 mdl = _CreateMdl(_GetProcessID());
3991 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3996 gctUINT32 order = get_order(bytes);
3998 if (order >= MAX_ORDER)
4000 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4003 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4005 alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
4007 mdl->u.contiguousPages = addr
4008 ? virt_to_page(addr)
4011 mdl->exact = gcvTRUE;
4013 mdl->u.contiguousPages =
4014 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
4016 if (mdl->u.contiguousPages == gcvNULL)
4018 mdl->u.contiguousPages =
4019 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
4021 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4022 mdl->exact = gcvFALSE;
4028 mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
4031 if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
4033 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4038 mdl->numPages = numPages;
4040 mdl->contiguous = Contiguous;
4042 for (i = 0; i < mdl->numPages; i++)
4046 if (mdl->contiguous)
4048 page = nth_page(mdl->u.contiguousPages, i);
4052 page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
4055 SetPageReserved(page);
4057 if (!PageHighMem(page) && page_to_phys(page))
4060 gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
4061 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
4067 /* Return physical address. */
4068 *Physical = (gctPHYS_ADDR) mdl;
4071 * Add this to a global list.
4072 * Will be used by get physical address
4073 * and mapuser pointer functions.
4077 /* Initialize the queue. */
4078 Os->mdlHead = Os->mdlTail = mdl;
4083 mdl->prev = Os->mdlTail;
4084 Os->mdlTail->next = mdl;
4091 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
4092 return gcvSTATUS_OK;
4097 /* Free the memory. */
4103 /* Unlock the memory. */
4107 /* Return the status. */
4112 /*******************************************************************************
4114 ** gckOS_FreePagedMemory
4116 ** Free memory allocated from the paged pool.
4121 ** Pointer to an gckOS object.
4123 ** gctPHYS_ADDR Physical
4124 ** Physical address of the allocation.
4127 ** Number of bytes of the allocation.
4134 gckOS_FreePagedMemory(
4136 IN gctPHYS_ADDR Physical,
4140 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
4143 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
4145 /* Verify the arguments. */
4146 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4147 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4148 gcmkVERIFY_ARGUMENT(Bytes > 0);
4150 /*addr = mdl->addr;*/
4154 for (i = 0; i < mdl->numPages; i++)
4156 if (mdl->contiguous)
4158 ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
4162 ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
4166 if (mdl->contiguous)
4168 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4169 if (mdl->exact == gcvTRUE)
4171 free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
4176 __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
4181 _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
4184 /* Remove the node from global list. */
4185 if (mdl == Os->mdlHead)
4187 if ((Os->mdlHead = mdl->next) == gcvNULL)
4189 Os->mdlTail = gcvNULL;
4194 mdl->prev->next = mdl->next;
4196 if (mdl == Os->mdlTail)
4198 Os->mdlTail = mdl->prev;
4202 mdl->next->prev = mdl->prev;
4208 /* Free the structure... */
4209 gcmkVERIFY_OK(_DestroyMdl(mdl));
4213 return gcvSTATUS_OK;
4216 /*******************************************************************************
4220 ** Lock memory allocated from the paged pool.
4225 ** Pointer to an gckOS object.
4227 ** gctPHYS_ADDR Physical
4228 ** Physical address of the allocation.
4231 ** Number of bytes of the allocation.
4233 ** gctBOOL Cacheable
4234 ** Cache mode of mapping.
4238 ** gctPOINTER * Logical
4239 ** Pointer to a variable that receives the address of the mapped
4242 ** gctSIZE_T * PageCount
4243 ** Pointer to a variable that receives the number of pages required for
4244 ** the page table according to the GPU page size.
4249 IN gctPHYS_ADDR Physical,
4251 IN gctBOOL Cacheable,
4252 OUT gctPOINTER * Logical,
4253 OUT gctSIZE_T * PageCount
4257 PLINUX_MDL_MAP mdlMap;
4259 unsigned long start;
4263 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
4265 /* Verify the arguments. */
4266 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4267 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4268 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4269 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
4271 mdl = (PLINUX_MDL) Physical;
4275 mdlMap = FindMdlMap(mdl, _GetProcessID());
4277 if (mdlMap == gcvNULL)
4279 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
4281 if (mdlMap == gcvNULL)
4285 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4286 return gcvSTATUS_OUT_OF_MEMORY;
4290 if (mdlMap->vmaAddr == gcvNULL)
4292 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
4293 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
4295 mdl->numPages * PAGE_SIZE,
4296 PROT_READ | PROT_WRITE,
4300 down_write(¤t->mm->mmap_sem);
4302 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
4304 mdl->numPages * PAGE_SIZE,
4305 PROT_READ | PROT_WRITE,
4309 up_write(¤t->mm->mmap_sem);
4313 gcvLEVEL_INFO, gcvZONE_OS,
4314 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
4315 __FUNCTION__, __LINE__,
4316 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
4317 (gctUINT32)(gctUINTPTR_T)mdl
4320 if (IS_ERR(mdlMap->vmaAddr))
4323 gcvLEVEL_INFO, gcvZONE_OS,
4324 "%s(%d): do_mmap_pgoff error",
4325 __FUNCTION__, __LINE__
4328 mdlMap->vmaAddr = gcvNULL;
4332 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4333 return gcvSTATUS_OUT_OF_MEMORY;
4336 down_write(¤t->mm->mmap_sem);
4338 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
4340 if (mdlMap->vma == gcvNULL)
4342 up_write(¤t->mm->mmap_sem);
4345 gcvLEVEL_INFO, gcvZONE_OS,
4346 "%s(%d): find_vma error",
4347 __FUNCTION__, __LINE__
4350 mdlMap->vmaAddr = gcvNULL;
4354 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
4355 return gcvSTATUS_OUT_OF_RESOURCES;
4358 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
4360 if (Cacheable == gcvFALSE)
4362 /* Make this mapping non-cached. */
4363 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
4368 /* Now map all the vmalloc pages to this user address. */
4369 if (mdl->contiguous)
4371 /* map kernel memory to user space.. */
4372 if (remap_pfn_range(mdlMap->vma,
4373 mdlMap->vma->vm_start,
4374 page_to_pfn(mdl->u.contiguousPages),
4375 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
4376 mdlMap->vma->vm_page_prot) < 0)
4378 up_write(¤t->mm->mmap_sem);
4381 gcvLEVEL_INFO, gcvZONE_OS,
4382 "%s(%d): unable to mmap ret",
4383 __FUNCTION__, __LINE__
4386 mdlMap->vmaAddr = gcvNULL;
4390 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4391 return gcvSTATUS_OUT_OF_MEMORY;
4396 start = mdlMap->vma->vm_start;
4398 for (i = 0; i < mdl->numPages; i++)
4400 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
4402 if (remap_pfn_range(mdlMap->vma,
4406 mdlMap->vma->vm_page_prot) < 0)
4408 up_write(¤t->mm->mmap_sem);
4411 gcvLEVEL_INFO, gcvZONE_OS,
4412 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
4413 __FUNCTION__, __LINE__,
4414 (gctUINT32)(gctUINTPTR_T)Physical,
4415 (gctUINT32)(gctUINTPTR_T)*Logical,
4416 (gctUINT32)(gctUINTPTR_T)addr,
4417 (gctUINT32)(gctUINTPTR_T)start
4420 mdlMap->vmaAddr = gcvNULL;
4424 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4425 return gcvSTATUS_OUT_OF_MEMORY;
4433 up_write(¤t->mm->mmap_sem);
4438 /* Convert pointer to MDL. */
4439 *Logical = mdlMap->vmaAddr;
4441 /* Return the page number according to the GPU page size. */
4442 gcmkASSERT((PAGE_SIZE % 4096) == 0);
4443 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
4445 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
4449 gcmkVERIFY_OK(gckOS_CacheFlush(
4454 (gctPOINTER)mdlMap->vmaAddr,
4455 mdl->numPages * PAGE_SIZE
4459 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
4460 return gcvSTATUS_OK;
4463 /*******************************************************************************
4467 ** Map paged memory into a page table.
4472 ** Pointer to an gckOS object.
4474 ** gctPHYS_ADDR Physical
4475 ** Physical address of the allocation.
4477 ** gctSIZE_T PageCount
4478 ** Number of pages required for the physical address.
4480 ** gctPOINTER PageTable
4481 ** Pointer to the page table to fill in.
4490 IN gctPHYS_ADDR Physical,
4491 IN gctSIZE_T PageCount,
4492 IN gctPOINTER PageTable
4495 return gckOS_MapPagesEx(Os,
4506 IN gctPHYS_ADDR Physical,
4507 IN gctSIZE_T PageCount,
4508 IN gctPOINTER PageTable
4511 gceSTATUS status = gcvSTATUS_OK;
4515 #if gcdNONPAGED_MEMORY_CACHEABLE
4519 gctPHYS_ADDR pageTablePhysical;
4522 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
4523 Os, Core, Physical, PageCount, PageTable);
4525 /* Verify the arguments. */
4526 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4527 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4528 gcmkVERIFY_ARGUMENT(PageCount > 0);
4529 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
4531 /* Convert pointer to MDL. */
4532 mdl = (PLINUX_MDL)Physical;
4535 gcvLEVEL_INFO, gcvZONE_OS,
4536 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4537 __FUNCTION__, __LINE__,
4538 (gctUINT32)(gctUINTPTR_T)Physical,
4539 (gctUINT32)(gctUINTPTR_T)PageCount,
4545 table = (gctUINT32 *)PageTable;
4546 #if gcdNONPAGED_MEMORY_CACHEABLE
4547 mmu = Os->device->kernels[Core]->mmu;
4548 bytes = PageCount * sizeof(*table);
4549 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4552 /* Get all the physical addresses and store them in the page table. */
4558 /* Try to get the user pages so DMA can happen. */
4559 while (PageCount-- > 0)
4562 if (Core == gcvCORE_VG)
4564 if (mdl->contiguous)
4567 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4568 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4574 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4575 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4582 if (mdl->contiguous)
4585 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4586 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4592 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4593 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4605 gcvLEVEL_INFO, gcvZONE_OS,
4606 "%s(%d): we should not get this call for Non Paged Memory!",
4607 __FUNCTION__, __LINE__
4610 while (PageCount-- > 0)
4613 if (Core == gcvCORE_VG)
4616 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4617 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4624 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4625 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4633 #if gcdNONPAGED_MEMORY_CACHEABLE
4634 /* Get physical address of pageTable */
4635 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4636 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4638 /* Flush the mmu page table cache. */
4639 gcmkONERROR(gckOS_CacheClean(
4653 /* Return the status. */
4658 /*******************************************************************************
4660 ** gckOS_UnlockPages
4662 ** Unlock memory allocated from the paged pool.
4667 ** Pointer to an gckOS object.
4669 ** gctPHYS_ADDR Physical
4670 ** Physical address of the allocation.
4673 ** Number of bytes of the allocation.
4675 ** gctPOINTER Logical
4676 ** Address of the mapped memory.
4685 IN gctPHYS_ADDR Physical,
4687 IN gctPOINTER Logical
4690 PLINUX_MDL_MAP mdlMap;
4691 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4693 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4694 Os, Physical, Bytes, Logical);
4696 /* Verify the arguments. */
4697 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4698 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4699 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4701 /* Make sure there is already a mapping...*/
4702 gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
4703 || mdl->u.contiguousPages != gcvNULL);
4709 while (mdlMap != gcvNULL)
4711 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4713 if (--mdlMap->count == 0)
4715 _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
4716 mdlMap->vmaAddr = gcvNULL;
4720 mdlMap = mdlMap->next;
4727 return gcvSTATUS_OK;
4731 /*******************************************************************************
4733 ** gckOS_AllocateContiguous
4735 ** Allocate memory from the contiguous pool.
4740 ** Pointer to an gckOS object.
4742 ** gctBOOL InUserSpace
4743 ** gcvTRUE if the pages need to be mapped into user space.
4745 ** gctSIZE_T * Bytes
4746 ** Pointer to the number of bytes to allocate.
4750 ** gctSIZE_T * Bytes
4751 ** Pointer to a variable that receives the number of bytes allocated.
4753 ** gctPHYS_ADDR * Physical
4754 ** Pointer to a variable that receives the physical address of the
4755 ** memory allocation.
4757 ** gctPOINTER * Logical
4758 ** Pointer to a variable that receives the logical address of the
4759 ** memory allocation.
4762 gckOS_AllocateContiguous(
4764 IN gctBOOL InUserSpace,
4765 IN OUT gctSIZE_T * Bytes,
4766 OUT gctPHYS_ADDR * Physical,
4767 OUT gctPOINTER * Logical
4772 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4773 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4775 /* Verify the arguments. */
4776 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4777 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4778 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4779 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4780 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4782 /* Same as non-paged memory for now. */
4783 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4790 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4791 *Bytes, *Physical, *Logical);
4792 return gcvSTATUS_OK;
4795 /* Return the status. */
4800 /*******************************************************************************
4802 ** gckOS_FreeContiguous
4804 ** Free memory allocated from the contiguous pool.
4809 ** Pointer to an gckOS object.
4811 ** gctPHYS_ADDR Physical
4812 ** Physical address of the allocation.
4814 ** gctPOINTER Logical
4815 ** Logicval address of the allocation.
4818 ** Number of bytes of the allocation.
4825 gckOS_FreeContiguous(
4827 IN gctPHYS_ADDR Physical,
4828 IN gctPOINTER Logical,
4834 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4835 Os, Physical, Logical, Bytes);
4837 /* Verify the arguments. */
4838 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4839 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4840 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4841 gcmkVERIFY_ARGUMENT(Bytes > 0);
4843 /* Same of non-paged memory for now. */
4844 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4848 return gcvSTATUS_OK;
4851 /* Return the status. */
4857 /******************************************************************************
4859 ** gckOS_GetKernelLogical
4861 ** Return the kernel logical pointer that corresponods to the specified
4862 ** hardware address.
4867 ** Pointer to an gckOS object.
4869 ** gctUINT32 Address
4870 ** Hardware physical address.
4874 ** gctPOINTER * KernelPointer
4875 ** Pointer to a variable receiving the pointer in kernel address space.
4878 gckOS_GetKernelLogical(
4880 IN gctUINT32 Address,
4881 OUT gctPOINTER * KernelPointer
4884 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4888 gckOS_GetKernelLogicalEx(
4891 IN gctUINT32 Address,
4892 OUT gctPOINTER * KernelPointer
4897 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4901 gckGALDEVICE device;
4907 /* Extract the pointer to the gckGALDEVICE class. */
4908 device = (gckGALDEVICE) Os->device;
4910 /* Kernel shortcut. */
4911 kernel = device->kernels[Core];
4913 if (Core == gcvCORE_VG)
4915 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4916 kernel->vg->hardware, Address, &pool, &offset
4922 /* Split the memory address into a pool type and offset. */
4923 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4924 kernel->hardware, Address, &pool, &offset
4928 /* Dispatch on pool. */
4931 case gcvPOOL_LOCAL_INTERNAL:
4932 /* Internal memory. */
4933 logical = device->internalLogical;
4936 case gcvPOOL_LOCAL_EXTERNAL:
4937 /* External memory. */
4938 logical = device->externalLogical;
4941 case gcvPOOL_SYSTEM:
4942 /* System memory. */
4943 logical = device->contiguousBase;
4947 /* Invalid memory pool. */
4949 return gcvSTATUS_INVALID_ARGUMENT;
4952 /* Build logical address of specified address. */
4953 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4956 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4957 return gcvSTATUS_OK;
4961 /* Return status. */
4967 /*******************************************************************************
4969 ** gckOS_MapUserPointer
4971 ** Map a pointer from the user process into the kernel address space.
4976 ** Pointer to an gckOS object.
4978 ** gctPOINTER Pointer
4979 ** Pointer in user process space that needs to be mapped.
4982 ** Number of bytes that need to be mapped.
4986 ** gctPOINTER * KernelPointer
4987 ** Pointer to a variable receiving the mapped pointer in kernel address
4991 gckOS_MapUserPointer(
4993 IN gctPOINTER Pointer,
4995 OUT gctPOINTER * KernelPointer
4998 gctPOINTER buf = gcvNULL;
5001 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
5003 /* Verify the arguments. */
5004 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5005 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5006 gcmkVERIFY_ARGUMENT(Size > 0);
5007 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5009 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
5014 "%s(%d): Failed to allocate memory.",
5015 __FUNCTION__, __LINE__
5018 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
5019 return gcvSTATUS_OUT_OF_MEMORY;
5022 len = copy_from_user(buf, Pointer, Size);
5027 "%s(%d): Failed to copy data from user.",
5028 __FUNCTION__, __LINE__
5036 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
5037 return gcvSTATUS_GENERIC_IO;
5040 *KernelPointer = buf;
5042 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
5043 return gcvSTATUS_OK;
5046 /*******************************************************************************
5048 ** gckOS_UnmapUserPointer
5050 ** Unmap a user process pointer from the kernel address space.
5055 ** Pointer to an gckOS object.
5057 ** gctPOINTER Pointer
5058 ** Pointer in user process space that needs to be unmapped.
5061 ** Number of bytes that need to be unmapped.
5063 ** gctPOINTER KernelPointer
5064 ** Pointer in kernel address space that needs to be unmapped.
5071 gckOS_UnmapUserPointer(
5073 IN gctPOINTER Pointer,
5075 IN gctPOINTER KernelPointer
5080 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
5081 Os, Pointer, Size, KernelPointer);
5084 /* Verify the arguments. */
5085 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5086 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5087 gcmkVERIFY_ARGUMENT(Size > 0);
5088 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5090 len = copy_to_user(Pointer, KernelPointer, Size);
5092 kfree(KernelPointer);
5098 "%s(%d): Failed to copy data to user.",
5099 __FUNCTION__, __LINE__
5102 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
5103 return gcvSTATUS_GENERIC_IO;
5107 return gcvSTATUS_OK;
5110 /*******************************************************************************
5112 ** gckOS_QueryNeedCopy
5114 ** Query whether the memory can be accessed or mapped directly or it has to be
5120 ** Pointer to an gckOS object.
5122 ** gctUINT32 ProcessID
5123 ** Process ID of the current process.
5127 ** gctBOOL_PTR NeedCopy
5128 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
5129 ** gcvFALSE if the memory can be accessed or mapped dircetly.
5132 gckOS_QueryNeedCopy(
5134 IN gctUINT32 ProcessID,
5135 OUT gctBOOL_PTR NeedCopy
5138 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
5140 /* Verify the arguments. */
5141 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5142 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
5144 /* We need to copy data. */
5145 *NeedCopy = gcvTRUE;
5148 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
5149 return gcvSTATUS_OK;
5152 /*******************************************************************************
5154 ** gckOS_CopyFromUserData
5156 ** Copy data from user to kernel memory.
5161 ** Pointer to an gckOS object.
5163 ** gctPOINTER KernelPointer
5164 ** Pointer to kernel memory.
5166 ** gctPOINTER Pointer
5167 ** Pointer to user memory.
5170 ** Number of bytes to copy.
5177 gckOS_CopyFromUserData(
5179 IN gctPOINTER KernelPointer,
5180 IN gctPOINTER Pointer,
5186 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5187 Os, KernelPointer, Pointer, Size);
5189 /* Verify the arguments. */
5190 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5191 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5192 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5193 gcmkVERIFY_ARGUMENT(Size > 0);
5195 /* Copy data from user. */
5196 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
5198 /* Could not copy all the bytes. */
5199 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5204 return gcvSTATUS_OK;
5207 /* Return the status. */
5212 /*******************************************************************************
5214 ** gckOS_CopyToUserData
5216 ** Copy data from kernel to user memory.
5221 ** Pointer to an gckOS object.
5223 ** gctPOINTER KernelPointer
5224 ** Pointer to kernel memory.
5226 ** gctPOINTER Pointer
5227 ** Pointer to user memory.
5230 ** Number of bytes to copy.
5237 gckOS_CopyToUserData(
5239 IN gctPOINTER KernelPointer,
5240 IN gctPOINTER Pointer,
5246 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5247 Os, KernelPointer, Pointer, Size);
5249 /* Verify the arguments. */
5250 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5251 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5252 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5253 gcmkVERIFY_ARGUMENT(Size > 0);
5255 /* Copy data to user. */
5256 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
5258 /* Could not copy all the bytes. */
5259 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5264 return gcvSTATUS_OK;
5267 /* Return the status. */
5272 /*******************************************************************************
5274 ** gckOS_WriteMemory
5276 ** Write data to a memory.
5281 ** Pointer to an gckOS object.
5283 ** gctPOINTER Address
5284 ** Address of the memory to write to.
5287 ** Data for register.
5296 IN gctPOINTER Address,
5301 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
5303 /* Verify the arguments. */
5304 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5307 if (access_ok(VERIFY_WRITE, Address, 4))
5310 if(put_user(Data, (gctUINT32*)Address))
5312 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
5317 /* Kernel address. */
5318 *(gctUINT32 *)Address = Data;
5323 return gcvSTATUS_OK;
5330 /*******************************************************************************
5332 ** gckOS_MapUserMemory
5334 ** Lock down a user buffer and return an DMA'able address to be used by the
5335 ** hardware to access it.
5339 ** gctPOINTER Memory
5340 ** Pointer to memory to lock down.
5343 ** Size in bytes of the memory to lock down.
5347 ** gctPOINTER * Info
5348 ** Pointer to variable receiving the information record required by
5349 ** gckOS_UnmapUserMemory.
5351 ** gctUINT32_PTR Address
5352 ** Pointer to a variable that will receive the address DMA'able by the
5356 gckOS_MapUserMemory(
5359 IN gctPOINTER Memory,
5360 IN gctUINT32 Physical,
5362 OUT gctPOINTER * Info,
5363 OUT gctUINT32_PTR Address
5368 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
5371 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
5374 return gcvSTATUS_OK;
5381 gctSIZE_T pageCount, i, j;
5382 gctUINT32_PTR pageTable;
5383 gctUINT32 address = 0, physical = ~0U;
5384 gctUINTPTR_T start, end, memory;
5388 gcsPageInfo_PTR info = gcvNULL;
5389 struct page **pages = gcvNULL;
5391 /* Verify the arguments. */
5392 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5393 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
5394 gcmkVERIFY_ARGUMENT(Size > 0);
5395 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5396 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5400 memory = (gctUINTPTR_T) Memory;
5402 /* Get the number of required pages. */
5403 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5404 start = memory >> PAGE_SHIFT;
5405 pageCount = end - start;
5408 gcvLEVEL_INFO, gcvZONE_OS,
5409 "%s(%d): pageCount: %d.",
5410 __FUNCTION__, __LINE__,
5415 if ((memory + Size) < memory)
5417 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5418 return gcvSTATUS_INVALID_ARGUMENT;
5421 MEMORY_MAP_LOCK(Os);
5423 /* Allocate the Info struct. */
5424 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
5426 if (info == gcvNULL)
5428 status = gcvSTATUS_OUT_OF_MEMORY;
5432 /* Allocate the array of page addresses. */
5433 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
5435 if (pages == gcvNULL)
5437 status = gcvSTATUS_OUT_OF_MEMORY;
5441 if (Physical != ~0U)
5443 for (i = 0; i < pageCount; i++)
5445 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
5451 /* Get the user pages. */
5452 down_read(¤t->mm->mmap_sem);
5454 result = get_user_pages(current,
5464 up_read(¤t->mm->mmap_sem);
5466 if (result <=0 || result < pageCount)
5468 struct vm_area_struct *vma;
5470 /* Release the pages if any. */
5473 for (i = 0; i < result; i++)
5475 if (pages[i] == gcvNULL)
5480 page_cache_release(pages[i]);
5487 vma = find_vma(current->mm, memory);
5489 if (vma && (vma->vm_flags & VM_PFNMAP))
5493 gctUINTPTR_T logical = memory;
5495 for (i = 0; i < pageCount; i++)
5497 pgd_t * pgd = pgd_offset(current->mm, logical);
5498 pud_t * pud = pud_offset(pgd, logical);
5502 pmd_t * pmd = pmd_offset(pud, logical);
5503 pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
5506 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5511 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5514 pages[i] = pte_page(*pte);
5515 pte_unmap_unlock(pte, ptl);
5517 /* Advance to next. */
5518 logical += PAGE_SIZE;
5523 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5526 /* Check if this memory is contiguous for old mmu. */
5527 if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
5529 for (i = 1; i < pageCount; i++)
5531 if (pages[i] != nth_page(pages[0], i))
5533 /* Non-contiguous. */
5540 /* Contiguous memory. */
5541 physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
5543 if (!((physical - Os->device->baseAddress) & 0x80000000))
5548 info->pages = gcvNULL;
5549 info->pageTable = gcvNULL;
5551 MEMORY_MAP_UNLOCK(Os);
5553 *Address = physical - Os->device->baseAddress;
5556 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5559 return gcvSTATUS_OK;
5564 /* Reference pages. */
5565 for (i = 0; i < pageCount; i++)
5572 for (i = 0; i < pageCount; i++)
5576 get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
5579 /* Flush(clean) the data cache. */
5580 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5581 (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
5582 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5587 if (Core == gcvCORE_VG)
5589 /* Allocate pages inside the page table. */
5590 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5591 pageCount * (PAGE_SIZE/4096),
5592 (gctPOINTER *) &pageTable,
5598 /* Allocate pages inside the page table. */
5599 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5600 pageCount * (PAGE_SIZE/4096),
5601 (gctPOINTER *) &pageTable,
5605 /* Fill the page table. */
5606 for (i = 0; i < pageCount; i++)
5609 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5611 phys = page_to_phys(pages[i]);
5614 if (Core == gcvCORE_VG)
5616 /* Get the physical address from page struct. */
5618 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5625 /* Get the physical address from page struct. */
5627 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5632 for (j = 1; j < (PAGE_SIZE/4096); j++)
5634 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5638 gcvLEVEL_INFO, gcvZONE_OS,
5639 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5640 __FUNCTION__, __LINE__,
5641 i, phys, pageTable[i]);
5645 if (Core == gcvCORE_VG)
5647 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5652 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
5655 /* Save pointer to page table. */
5656 info->pageTable = pageTable;
5657 info->pages = pages;
5659 *Info = (gctPOINTER) info;
5662 gcvLEVEL_INFO, gcvZONE_OS,
5663 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5664 __FUNCTION__, __LINE__,
5670 offset = (Physical != ~0U)
5671 ? (Physical & ~PAGE_MASK)
5672 : (memory & ~PAGE_MASK);
5674 /* Return address. */
5675 *Address = address + offset;
5678 gcvLEVEL_INFO, gcvZONE_OS,
5679 "%s(%d): Address: 0x%X.",
5680 __FUNCTION__, __LINE__,
5685 status = gcvSTATUS_OK;
5691 if (gcmIS_ERROR(status))
5695 "%s(%d): error occured: %d.",
5696 __FUNCTION__, __LINE__,
5700 /* Release page array. */
5701 if (result > 0 && pages != gcvNULL)
5705 "%s(%d): error: page table is freed.",
5706 __FUNCTION__, __LINE__
5709 for (i = 0; i < result; i++)
5711 if (pages[i] == gcvNULL)
5715 page_cache_release(pages[i]);
5719 if (info!= gcvNULL && pages != gcvNULL)
5723 "%s(%d): error: pages is freed.",
5724 __FUNCTION__, __LINE__
5727 /* Free the page table. */
5729 info->pages = gcvNULL;
5732 /* Release page info struct. */
5733 if (info != gcvNULL)
5737 "%s(%d): error: info is freed.",
5738 __FUNCTION__, __LINE__
5741 /* Free the page info struct. */
5747 MEMORY_MAP_UNLOCK(Os);
5749 /* Return the status. */
5750 if (gcmIS_SUCCESS(status))
5752 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5764 /*******************************************************************************
5766 ** gckOS_UnmapUserMemory
5768 ** Unlock a user buffer and that was previously locked down by
5769 ** gckOS_MapUserMemory.
5773 ** gctPOINTER Memory
5774 ** Pointer to memory to unlock.
5777 ** Size in bytes of the memory to unlock.
5780 ** Information record returned by gckOS_MapUserMemory.
5782 ** gctUINT32_PTR Address
5783 ** The address returned by gckOS_MapUserMemory.
5790 gckOS_UnmapUserMemory(
5793 IN gctPOINTER Memory,
5796 IN gctUINT32 Address
5801 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5802 Os, Core, Memory, Size, Info, Address);
5805 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5808 return gcvSTATUS_OK;
5815 gctUINTPTR_T memory, start, end;
5816 gcsPageInfo_PTR info;
5817 gctSIZE_T pageCount, i;
5818 struct page **pages;
5820 /* Verify the arguments. */
5821 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5822 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5823 gcmkVERIFY_ARGUMENT(Size > 0);
5824 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5828 info = (gcsPageInfo_PTR) Info;
5830 pages = info->pages;
5833 gcvLEVEL_INFO, gcvZONE_OS,
5834 "%s(%d): info=0x%X, pages=0x%X.",
5835 __FUNCTION__, __LINE__,
5839 /* Invalid page array. */
5840 if (pages == gcvNULL && info->pageTable == gcvNULL)
5845 return gcvSTATUS_OK;
5848 memory = (gctUINTPTR_T)Memory;
5849 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5850 start = memory >> PAGE_SHIFT;
5851 pageCount = end - start;
5854 if ((memory + Size) < memory)
5856 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5857 return gcvSTATUS_INVALID_ARGUMENT;
5861 gcvLEVEL_INFO, gcvZONE_OS,
5862 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5863 __FUNCTION__, __LINE__,
5864 memory, pageCount, info->pageTable
5867 MEMORY_MAP_LOCK(Os);
5869 gcmkASSERT(info->pageTable != gcvNULL);
5872 if (Core == gcvCORE_VG)
5874 /* Free the pages from the MMU. */
5875 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5877 pageCount * (PAGE_SIZE/4096)
5883 /* Free the pages from the MMU. */
5884 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5886 pageCount * (PAGE_SIZE/4096)
5890 /* Release the page cache. */
5893 for (i = 0; i < pageCount; i++)
5896 gcvLEVEL_INFO, gcvZONE_OS,
5897 "%s(%d): pages[%d]: 0x%X.",
5898 __FUNCTION__, __LINE__,
5902 if (!PageReserved(pages[i]))
5904 SetPageDirty(pages[i]);
5907 page_cache_release(pages[i]);
5912 status = gcvSTATUS_OK;
5916 if (info != gcvNULL)
5918 /* Free the page array. */
5919 if (info->pages != gcvNULL)
5927 MEMORY_MAP_UNLOCK(Os);
5929 /* Return the status. */
5936 /*******************************************************************************
5938 ** gckOS_GetBaseAddress
5940 ** Get the base address for the physical memory.
5945 ** Pointer to the gckOS object.
5949 ** gctUINT32_PTR BaseAddress
5950 ** Pointer to a variable that will receive the base address.
5953 gckOS_GetBaseAddress(
5955 OUT gctUINT32_PTR BaseAddress
5958 gcmkHEADER_ARG("Os=0x%X", Os);
5960 /* Verify the arguments. */
5961 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5962 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5964 /* Return base address. */
5965 *BaseAddress = Os->device->baseAddress;
5968 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5969 return gcvSTATUS_OK;
5973 gckOS_SuspendInterrupt(
5977 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5981 gckOS_SuspendInterruptEx(
5986 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5988 /* Verify the arguments. */
5989 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5991 disable_irq(Os->device->irqLines[Core]);
5994 return gcvSTATUS_OK;
5998 gckOS_ResumeInterrupt(
6002 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
6006 gckOS_ResumeInterruptEx(
6011 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
6013 /* Verify the arguments. */
6014 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6016 enable_irq(Os->device->irqLines[Core]);
6019 return gcvSTATUS_OK;
6024 IN gctPOINTER Destination,
6025 IN gctCONST_POINTER Source,
6029 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
6030 Destination, Source, Bytes);
6032 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
6033 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
6034 gcmkVERIFY_ARGUMENT(Bytes > 0);
6036 memcpy(Destination, Source, Bytes);
6039 return gcvSTATUS_OK;
6044 IN gctPOINTER Memory,
6048 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
6050 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
6051 gcmkVERIFY_ARGUMENT(Bytes > 0);
6053 memset(Memory, 0, Bytes);
6056 return gcvSTATUS_OK;
6059 /*******************************************************************************
6060 ********************************* Cache Control ********************************
6061 *******************************************************************************/
6063 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
6064 static inline gceSTATUS
6066 gceCACHEOPERATION Type,
6067 unsigned long Start,
6073 case gcvCACHE_CLEAN:
6074 outer_clean_range(Start, End);
6076 case gcvCACHE_INVALIDATE:
6077 outer_inv_range(Start, End);
6079 case gcvCACHE_FLUSH:
6080 outer_flush_range(Start, End);
6083 return gcvSTATUS_INVALID_ARGUMENT;
6086 return gcvSTATUS_OK;
6089 #if gcdENABLE_OUTER_CACHE_PATCH
6090 /*******************************************************************************
6091 ** _HandleOuterCache
6093 ** Handle the outer cache for the specified addresses.
6098 ** Pointer to gckOS object.
6100 ** gctUINT32 ProcessID
6101 ** Process ID Logical belongs.
6103 ** gctPHYS_ADDR Handle
6104 ** Physical address handle. If gcvNULL it is video memory.
6106 ** gctPOINTER Physical
6107 ** Physical address to flush.
6109 ** gctPOINTER Logical
6110 ** Logical address to flush.
6113 ** Size of the address range in bytes to flush.
6115 ** gceOUTERCACHE_OPERATION Type
6116 ** Operation need to be execute.
6121 IN gctUINT32 ProcessID,
6122 IN gctPHYS_ADDR Handle,
6123 IN gctPOINTER Physical,
6124 IN gctPOINTER Logical,
6126 IN gceCACHEOPERATION Type
6130 gctUINT32 i, pageNum;
6131 unsigned long paddr;
6134 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6135 Os, ProcessID, Handle, Logical, Bytes);
6137 if (Physical != gcvNULL)
6139 /* Non paged memory or gcvPOOL_USER surface */
6140 paddr = (unsigned long) Physical;
6141 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6143 else if ((Handle == gcvNULL)
6144 || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
6147 /* Video Memory or contiguous virtual memory */
6148 gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
6149 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6153 /* Non contiguous virtual memory */
6154 vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
6155 pageNum = GetPageCount(Bytes, 0);
6157 for (i = 0; i < pageNum; i += 1)
6159 gcmkONERROR(_ConvertLogical2Physical(
6161 vaddr + PAGE_SIZE * i,
6167 gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
6175 return gcvSTATUS_OK;
6178 /* Return the status. */
6185 /*******************************************************************************
6188 ** Clean the cache for the specified addresses. The GPU is going to need the
6189 ** data. If the system is allocating memory as non-cachable, this function can
6195 ** Pointer to gckOS object.
6197 ** gctUINT32 ProcessID
6198 ** Process ID Logical belongs.
6200 ** gctPHYS_ADDR Handle
6201 ** Physical address handle. If gcvNULL it is video memory.
6203 ** gctPOINTER Physical
6204 ** Physical address to flush.
6206 ** gctPOINTER Logical
6207 ** Logical address to flush.
6210 ** Size of the address range in bytes to flush.
6215 IN gctUINT32 ProcessID,
6216 IN gctPHYS_ADDR Handle,
6217 IN gctPOINTER Physical,
6218 IN gctPOINTER Logical,
6222 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6223 Os, ProcessID, Handle, Logical, Bytes);
6225 /* Verify the arguments. */
6226 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6227 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6228 gcmkVERIFY_ARGUMENT(Bytes > 0);
6230 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6234 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6235 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
6237 dmac_clean_range(Logical, Logical + Bytes);
6240 #if defined(CONFIG_OUTER_CACHE)
6242 #if gcdENABLE_OUTER_CACHE_PATCH
6243 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
6245 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6249 #elif defined(CONFIG_MIPS)
6251 dma_cache_wback((unsigned long) Logical, Bytes);
6253 #elif defined(CONFIG_PPC)
6258 dma_sync_single_for_device(
6260 (dma_addr_t)Physical,
6268 return gcvSTATUS_OK;
6271 /*******************************************************************************
6272 ** gckOS_CacheInvalidate
6274 ** Invalidate the cache for the specified addresses. The GPU is going to need
6275 ** data. If the system is allocating memory as non-cachable, this function can
6281 ** Pointer to gckOS object.
6283 ** gctUINT32 ProcessID
6284 ** Process ID Logical belongs.
6286 ** gctPHYS_ADDR Handle
6287 ** Physical address handle. If gcvNULL it is video memory.
6289 ** gctPOINTER Logical
6290 ** Logical address to flush.
6293 ** Size of the address range in bytes to flush.
6296 gckOS_CacheInvalidate(
6298 IN gctUINT32 ProcessID,
6299 IN gctPHYS_ADDR Handle,
6300 IN gctPOINTER Physical,
6301 IN gctPOINTER Logical,
6305 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6306 Os, ProcessID, Handle, Logical, Bytes);
6308 /* Verify the arguments. */
6309 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6310 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6311 gcmkVERIFY_ARGUMENT(Bytes > 0);
6313 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6317 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6318 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
6320 dmac_inv_range(Logical, Logical + Bytes);
6323 #if defined(CONFIG_OUTER_CACHE)
6325 #if gcdENABLE_OUTER_CACHE_PATCH
6326 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
6328 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6332 #elif defined(CONFIG_MIPS)
6333 dma_cache_inv((unsigned long) Logical, Bytes);
6334 #elif defined(CONFIG_PPC)
6337 dma_sync_single_for_device(
6339 (dma_addr_t)Physical,
6347 return gcvSTATUS_OK;
6350 /*******************************************************************************
6353 ** Clean the cache for the specified addresses and invalidate the lines as
6354 ** well. The GPU is going to need and modify the data. If the system is
6355 ** allocating memory as non-cachable, this function can be ignored.
6360 ** Pointer to gckOS object.
6362 ** gctUINT32 ProcessID
6363 ** Process ID Logical belongs.
6365 ** gctPHYS_ADDR Handle
6366 ** Physical address handle. If gcvNULL it is video memory.
6368 ** gctPOINTER Logical
6369 ** Logical address to flush.
6372 ** Size of the address range in bytes to flush.
6377 IN gctUINT32 ProcessID,
6378 IN gctPHYS_ADDR Handle,
6379 IN gctPOINTER Physical,
6380 IN gctPOINTER Logical,
6384 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6385 Os, ProcessID, Handle, Logical, Bytes);
6387 /* Verify the arguments. */
6388 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6389 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6390 gcmkVERIFY_ARGUMENT(Bytes > 0);
6392 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6395 dmac_flush_range(Logical, Logical + Bytes);
6397 #if defined(CONFIG_OUTER_CACHE)
6399 #if gcdENABLE_OUTER_CACHE_PATCH
6400 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6402 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6406 #elif defined(CONFIG_MIPS)
6407 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6408 #elif defined(CONFIG_PPC)
6411 dma_sync_single_for_device(
6413 (dma_addr_t)Physical,
6421 return gcvSTATUS_OK;
6424 /*******************************************************************************
6425 ********************************* Broadcasting *********************************
6426 *******************************************************************************/
6428 /*******************************************************************************
6432 ** System hook for broadcast events from the kernel driver.
6437 ** Pointer to the gckOS object.
6439 ** gckHARDWARE Hardware
6440 ** Pointer to the gckHARDWARE object.
6442 ** gceBROADCAST Reason
6443 ** Reason for the broadcast. Can be one of the following values:
6445 ** gcvBROADCAST_GPU_IDLE
6446 ** Broadcasted when the kernel driver thinks the GPU might be
6447 ** idle. This can be used to handle power management.
6449 ** gcvBROADCAST_GPU_COMMIT
6450 ** Broadcasted when any client process commits a command
6451 ** buffer. This can be used to handle power management.
6453 ** gcvBROADCAST_GPU_STUCK
6454 ** Broadcasted when the kernel driver hits the timeout waiting
6457 ** gcvBROADCAST_FIRST_PROCESS
6458 ** First process is trying to connect to the kernel.
6460 ** gcvBROADCAST_LAST_PROCESS
6461 ** Last process has detached from the kernel.
6470 IN gckHARDWARE Hardware,
6471 IN gceBROADCAST Reason
6476 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6478 /* Verify the arguments. */
6479 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6480 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6484 case gcvBROADCAST_FIRST_PROCESS:
6485 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6488 case gcvBROADCAST_LAST_PROCESS:
6489 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6493 gckHARDWARE_SetPowerManagementState(Hardware,
6494 gcvPOWER_OFF_BROADCAST));
6497 case gcvBROADCAST_GPU_IDLE:
6498 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6502 gckHARDWARE_SetPowerManagementState(Hardware,
6503 #if gcdPOWER_SUSNPEND_WHEN_IDLE
6504 gcvPOWER_SUSPEND_BROADCAST));
6506 gcvPOWER_IDLE_BROADCAST));
6509 /* Add idle process DB. */
6510 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6513 gcvNULL, gcvNULL, 0));
6516 case gcvBROADCAST_GPU_COMMIT:
6517 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6519 /* Add busy process DB. */
6520 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6523 gcvNULL, gcvNULL, 0));
6527 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6530 case gcvBROADCAST_GPU_STUCK:
6531 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6532 #if !gcdENABLE_RECOVERY
6533 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6535 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6538 case gcvBROADCAST_AXI_BUS_ERROR:
6539 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6540 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6541 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6547 return gcvSTATUS_OK;
6550 /* Return the status. */
6555 /*******************************************************************************
6557 ** gckOS_BroadcastHurry
6559 ** The GPU is running too slow.
6564 ** Pointer to the gckOS object.
6566 ** gckHARDWARE Hardware
6567 ** Pointer to the gckHARDWARE object.
6570 ** The higher the number, the higher the urgency to speed up the GPU.
6571 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6578 gckOS_BroadcastHurry(
6580 IN gckHARDWARE Hardware,
6584 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6586 /* Do whatever you need to do to speed up the GPU now. */
6590 return gcvSTATUS_OK;
6593 /*******************************************************************************
6595 ** gckOS_BroadcastCalibrateSpeed
6597 ** Calibrate the speed of the GPU.
6602 ** Pointer to the gckOS object.
6604 ** gckHARDWARE Hardware
6605 ** Pointer to the gckHARDWARE object.
6607 ** gctUINT Idle, Time
6608 ** Idle/Time will give the percentage the GPU is idle, so you can use
6609 ** this to calibrate the working point of the GPU.
6616 gckOS_BroadcastCalibrateSpeed(
6618 IN gckHARDWARE Hardware,
6623 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6624 Os, Hardware, Idle, Time);
6626 /* Do whatever you need to do to callibrate the GPU speed. */
6630 return gcvSTATUS_OK;
6633 /*******************************************************************************
6634 ********************************** Semaphores **********************************
6635 *******************************************************************************/
6637 /*******************************************************************************
6639 ** gckOS_CreateSemaphore
6641 ** Create a semaphore.
6646 ** Pointer to the gckOS object.
6650 ** gctPOINTER * Semaphore
6651 ** Pointer to the variable that will receive the created semaphore.
6654 gckOS_CreateSemaphore(
6656 OUT gctPOINTER * Semaphore
6660 struct semaphore *sem = gcvNULL;
6662 gcmkHEADER_ARG("Os=0x%X", Os);
6664 /* Verify the arguments. */
6665 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6666 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6668 /* Allocate the semaphore structure. */
6669 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6672 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6675 /* Initialize the semaphore. */
6678 /* Return to caller. */
6679 *Semaphore = (gctPOINTER) sem;
6683 return gcvSTATUS_OK;
6686 /* Return the status. */
6691 /*******************************************************************************
6693 ** gckOS_AcquireSemaphore
6695 ** Acquire a semaphore.
6700 ** Pointer to the gckOS object.
6702 ** gctPOINTER Semaphore
6703 ** Pointer to the semaphore thet needs to be acquired.
6710 gckOS_AcquireSemaphore(
6712 IN gctPOINTER Semaphore
6717 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6719 /* Verify the arguments. */
6720 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6721 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6723 /* Acquire the semaphore. */
6724 if (down_interruptible((struct semaphore *) Semaphore))
6726 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6731 return gcvSTATUS_OK;
6734 /* Return the status. */
6739 /*******************************************************************************
6741 ** gckOS_TryAcquireSemaphore
6743 ** Try to acquire a semaphore.
6748 ** Pointer to the gckOS object.
6750 ** gctPOINTER Semaphore
6751 ** Pointer to the semaphore thet needs to be acquired.
6758 gckOS_TryAcquireSemaphore(
6760 IN gctPOINTER Semaphore
6765 gcmkHEADER_ARG("Os=0x%x", Os);
6767 /* Verify the arguments. */
6768 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6769 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6771 /* Acquire the semaphore. */
6772 if (down_trylock((struct semaphore *) Semaphore))
6775 status = gcvSTATUS_TIMEOUT;
6782 return gcvSTATUS_OK;
6785 /*******************************************************************************
6787 ** gckOS_ReleaseSemaphore
6789 ** Release a previously acquired semaphore.
6794 ** Pointer to the gckOS object.
6796 ** gctPOINTER Semaphore
6797 ** Pointer to the semaphore thet needs to be released.
6804 gckOS_ReleaseSemaphore(
6806 IN gctPOINTER Semaphore
6809 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6811 /* Verify the arguments. */
6812 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6813 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6815 /* Release the semaphore. */
6816 up((struct semaphore *) Semaphore);
6820 return gcvSTATUS_OK;
6823 /*******************************************************************************
6825 ** gckOS_DestroySemaphore
6827 ** Destroy a semaphore.
6832 ** Pointer to the gckOS object.
6834 ** gctPOINTER Semaphore
6835 ** Pointer to the semaphore thet needs to be destroyed.
6842 gckOS_DestroySemaphore(
6844 IN gctPOINTER Semaphore
6847 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6849 /* Verify the arguments. */
6850 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6851 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6853 /* Free the sempahore structure. */
6858 return gcvSTATUS_OK;
6861 /*******************************************************************************
6863 ** gckOS_GetProcessID
6865 ** Get current process ID.
6873 ** gctUINT32_PTR ProcessID
6874 ** Pointer to the variable that receives the process ID.
6878 OUT gctUINT32_PTR ProcessID
6881 /* Get process ID. */
6882 if (ProcessID != gcvNULL)
6884 *ProcessID = _GetProcessID();
6888 return gcvSTATUS_OK;
6891 /*******************************************************************************
6893 ** gckOS_GetThreadID
6895 ** Get current thread ID.
6903 ** gctUINT32_PTR ThreadID
6904 ** Pointer to the variable that receives the thread ID.
6908 OUT gctUINT32_PTR ThreadID
6911 /* Get thread ID. */
6912 if (ThreadID != gcvNULL)
6914 *ThreadID = _GetThreadID();
6918 return gcvSTATUS_OK;
6921 /*******************************************************************************
6923 ** gckOS_SetGPUPower
6925 ** Set the power of the GPU on or off.
6930 ** Pointer to a gckOS object.
6933 ** GPU whose power is set.
6936 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6939 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6953 struct clk *clk_3dcore = Os->device->clk_3d_core;
6954 struct clk *clk_3dshader = Os->device->clk_3d_shader;
6955 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
6956 struct clk *clk_3d_axi = Os->device->clk_3d_axi;
6958 struct clk *clk_2dcore = Os->device->clk_2d_core;
6959 struct clk *clk_2d_axi = Os->device->clk_2d_axi;
6960 struct clk *clk_vg_axi = Os->device->clk_vg_axi;
6961 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6965 gctBOOL oldClockState = gcvFALSE;
6966 gctBOOL oldPowerState = gcvFALSE;
6968 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6970 if (Os->device->kernels[Core] != NULL)
6973 if (Core == gcvCORE_VG)
6975 oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
6976 oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
6981 oldClockState = Os->device->kernels[Core]->hardware->clockState;
6982 oldPowerState = Os->device->kernels[Core]->hardware->powerState;
6987 if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
6989 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6990 if(!IS_ERR(Os->device->gpu_regulator)) {
6991 ret = regulator_enable(Os->device->gpu_regulator);
6993 gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
6994 __FUNCTION__, __LINE__, ret);
6997 imx_gpc_power_up_pu(true);
7001 pm_runtime_get_sync(Os->device->pmdev);
7005 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7006 if (Clock == gcvTRUE) {
7007 if (oldClockState == gcvFALSE) {
7010 clk_enable(clk_3dcore);
7012 clk_enable(clk_3dshader);
7015 clk_enable(clk_2dcore);
7016 clk_enable(clk_2d_axi);
7019 clk_enable(clk_2dcore);
7020 clk_enable(clk_vg_axi);
7027 if (oldClockState == gcvTRUE) {
7031 clk_disable(clk_3dshader);
7032 clk_disable(clk_3dcore);
7035 clk_disable(clk_2dcore);
7036 clk_disable(clk_2d_axi);
7039 clk_disable(clk_2dcore);
7040 clk_disable(clk_vg_axi);
7048 if (Clock == gcvTRUE) {
7049 if (oldClockState == gcvFALSE) {
7052 clk_prepare(clk_3dcore);
7053 clk_enable(clk_3dcore);
7054 clk_prepare(clk_3dshader);
7055 clk_enable(clk_3dshader);
7056 clk_prepare(clk_3d_axi);
7057 clk_enable(clk_3d_axi);
7060 clk_prepare(clk_2dcore);
7061 clk_enable(clk_2dcore);
7062 clk_prepare(clk_2d_axi);
7063 clk_enable(clk_2d_axi);
7066 clk_prepare(clk_2dcore);
7067 clk_enable(clk_2dcore);
7068 clk_prepare(clk_vg_axi);
7069 clk_enable(clk_vg_axi);
7076 if (oldClockState == gcvTRUE) {
7079 clk_disable(clk_3dshader);
7080 clk_unprepare(clk_3dshader);
7081 clk_disable(clk_3dcore);
7082 clk_unprepare(clk_3dcore);
7083 clk_disable(clk_3d_axi);
7084 clk_unprepare(clk_3d_axi);
7087 clk_disable(clk_2dcore);
7088 clk_unprepare(clk_2dcore);
7089 clk_disable(clk_2d_axi);
7090 clk_unprepare(clk_2d_axi);
7093 clk_disable(clk_2dcore);
7094 clk_unprepare(clk_2dcore);
7095 clk_disable(clk_vg_axi);
7096 clk_unprepare(clk_vg_axi);
7104 if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
7107 pm_runtime_put_sync(Os->device->pmdev);
7110 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7111 if(!IS_ERR(Os->device->gpu_regulator))
7112 regulator_disable(Os->device->gpu_regulator);
7114 imx_gpc_power_up_pu(false);
7118 /* TODO: Put your code here. */
7120 return gcvSTATUS_OK;
7123 /*******************************************************************************
7132 ** Pointer to a gckOS object.
7135 ** GPU whose power is set.
7147 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7148 #define SRC_SCR_OFFSET 0
7149 #define BP_SRC_SCR_GPU3D_RST 1
7150 #define BP_SRC_SCR_GPU2D_RST 4
7151 void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
7152 gctUINT32 bit_offset,val;
7154 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
7156 if(Core == gcvCORE_MAJOR) {
7157 bit_offset = BP_SRC_SCR_GPU3D_RST;
7158 } else if((Core == gcvCORE_VG)
7159 ||(Core == gcvCORE_2D)) {
7160 bit_offset = BP_SRC_SCR_GPU2D_RST;
7162 return gcvSTATUS_INVALID_CONFIG;
7164 val = __raw_readl(src_base + SRC_SCR_OFFSET);
7165 val &= ~(1 << (bit_offset));
7166 val |= (1 << (bit_offset));
7167 __raw_writel(val, src_base + SRC_SCR_OFFSET);
7169 while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
7170 (1 << (bit_offset))) != 0) {
7174 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7175 struct reset_control *rstc = Os->device->rstc[Core];
7177 reset_control_reset(rstc);
7179 imx_src_reset_gpu((int)Core);
7181 return gcvSTATUS_OK;
7184 /*******************************************************************************
7186 ** gckOS_PrepareGPUFrequency
7188 ** Prepare to set GPU frequency and voltage.
7193 ** Pointer to a gckOS object.
7196 ** GPU whose frequency and voltage will be set.
7203 gckOS_PrepareGPUFrequency(
7208 return gcvSTATUS_OK;
7211 /*******************************************************************************
7213 ** gckOS_FinishGPUFrequency
7215 ** Finish GPU frequency setting.
7220 ** Pointer to a gckOS object.
7223 ** GPU whose frequency and voltage is set.
7230 gckOS_FinishGPUFrequency(
7235 return gcvSTATUS_OK;
7238 /*******************************************************************************
7240 ** gckOS_QueryGPUFrequency
7242 ** Query the current frequency of the GPU.
7247 ** Pointer to a gckOS object.
7250 ** GPU whose power is set.
7252 ** gctUINT32 * Frequency
7253 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
7256 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
7263 gckOS_QueryGPUFrequency(
7266 OUT gctUINT32 * Frequency,
7267 OUT gctUINT8 * Scale
7270 return gcvSTATUS_OK;
7273 /*******************************************************************************
7275 ** gckOS_SetGPUFrequency
7277 ** Set frequency and voltage of the GPU.
7279 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
7280 ** a real frequency according to this scale and board's configure.
7282 ** 2. BSP should find a suitable voltage for this frequency.
7284 ** 3. BSP must make sure setting take effect before this function returns.
7289 ** Pointer to a gckOS object.
7292 ** GPU whose power is set.
7295 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
7296 ** full frequency and 64 means 64/64 of full frequency.
7303 gckOS_SetGPUFrequency(
7309 return gcvSTATUS_OK;
7312 /*----------------------------------------------------------------------------*/
7313 /*----- Profile --------------------------------------------------------------*/
7316 gckOS_GetProfileTick(
7317 OUT gctUINT64_PTR Tick
7320 struct timespec time;
7322 ktime_get_ts(&time);
7324 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
7326 return gcvSTATUS_OK;
7330 gckOS_QueryProfileTickRate(
7331 OUT gctUINT64_PTR TickRate
7334 struct timespec res;
7336 hrtimer_get_res(CLOCK_MONOTONIC, &res);
7338 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
7340 return gcvSTATUS_OK;
7348 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
7349 return div_u64(Ticks, 1000000);
7351 gctUINT64 rem = Ticks;
7352 gctUINT64 b = 1000000;
7353 gctUINT64 res, d = 1;
7354 gctUINT32 high = rem >> 32;
7356 /* Reduce the thing a bit first */
7358 if (high >= 1000000)
7361 res = (gctUINT64) high << 32;
7362 rem -= (gctUINT64) (high * 1000000) << 32;
7365 while (((gctINT64) b > 0) && (b < rem))
7384 return (gctUINT32) res;
7388 /******************************************************************************\
7389 ******************************* Signal Management ******************************
7390 \******************************************************************************/
7393 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
7395 /*******************************************************************************
7397 ** gckOS_CreateSignal
7399 ** Create a new signal.
7404 ** Pointer to an gckOS object.
7406 ** gctBOOL ManualReset
7407 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7408 ** order to set the signal to nonsignaled state.
7409 ** If set to gcvFALSE, the signal will automatically be set to
7410 ** nonsignaled state by gckOS_WaitSignal function.
7414 ** gctSIGNAL * Signal
7415 ** Pointer to a variable receiving the created gctSIGNAL.
7420 IN gctBOOL ManualReset,
7421 OUT gctSIGNAL * Signal
7425 gcsSIGNAL_PTR signal;
7427 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
7429 /* Verify the arguments. */
7430 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7431 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7433 /* Create an event structure. */
7434 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
7436 if (signal == gcvNULL)
7438 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7441 /* Save the process ID. */
7442 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
7443 signal->manualReset = ManualReset;
7444 signal->hardware = gcvNULL;
7445 init_completion(&signal->obj);
7446 atomic_set(&signal->ref, 1);
7448 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
7450 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
7452 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
7453 return gcvSTATUS_OK;
7456 if (signal != gcvNULL)
7466 gckOS_SignalQueryHardware(
7468 IN gctSIGNAL Signal,
7469 OUT gckHARDWARE * Hardware
7473 gcsSIGNAL_PTR signal;
7475 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7477 /* Verify the arguments. */
7478 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7479 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7480 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7482 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7484 *Hardware = signal->hardware;
7487 return gcvSTATUS_OK;
7494 gckOS_SignalSetHardware(
7496 IN gctSIGNAL Signal,
7497 IN gckHARDWARE Hardware
7501 gcsSIGNAL_PTR signal;
7503 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7505 /* Verify the arguments. */
7506 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7507 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7509 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7511 signal->hardware = Hardware;
7514 return gcvSTATUS_OK;
7520 /*******************************************************************************
7522 ** gckOS_DestroySignal
7524 ** Destroy a signal.
7529 ** Pointer to an gckOS object.
7532 ** Pointer to the gctSIGNAL.
7539 gckOS_DestroySignal(
7545 gcsSIGNAL_PTR signal;
7546 gctBOOL acquired = gcvFALSE;
7548 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7550 /* Verify the arguments. */
7551 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7552 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7554 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7557 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7559 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7561 if (atomic_dec_and_test(&signal->ref))
7563 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7565 /* Free the sgianl. */
7569 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7570 acquired = gcvFALSE;
7574 return gcvSTATUS_OK;
7579 /* Release the mutex. */
7580 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7587 /*******************************************************************************
7591 ** Set a state of the specified signal.
7596 ** Pointer to an gckOS object.
7599 ** Pointer to the gctSIGNAL.
7602 ** If gcvTRUE, the signal will be set to signaled state.
7603 ** If gcvFALSE, the signal will be set to nonsignaled state.
7612 IN gctSIGNAL Signal,
7617 gcsSIGNAL_PTR signal;
7618 gctBOOL acquired = gcvFALSE;
7620 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7622 /* Verify the arguments. */
7623 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7624 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7626 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7629 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7631 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7635 /* unbind the signal from hardware. */
7636 signal->hardware = gcvNULL;
7638 /* Set the event to a signaled state. */
7639 complete(&signal->obj);
7643 /* Set the event to an unsignaled state. */
7644 INIT_COMPLETION(signal->obj);
7647 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7648 acquired = gcvFALSE;
7652 return gcvSTATUS_OK;
7657 /* Release the mutex. */
7658 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7669 IN gctHANDLE Process,
7675 struct task_struct * userTask;
7676 struct siginfo info;
7678 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7680 if (userTask != gcvNULL)
7683 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7686 info.si_ptr = (gctPOINTER) Signal;
7688 /* Signals with numbers between 32 and 63 are real-time,
7689 send a real-time signal to the user process. */
7690 result = send_sig_info(48, &info, userTask);
7692 printk("gckOS_SetSignalVG:0x%x\n", result);
7696 status = gcvSTATUS_GENERIC_IO;
7700 "%s(%d): an error has occurred.\n",
7701 __FUNCTION__, __LINE__
7706 status = gcvSTATUS_OK;
7711 status = gcvSTATUS_GENERIC_IO;
7715 "%s(%d): an error has occurred.\n",
7716 __FUNCTION__, __LINE__
7720 /* Return status. */
7725 /*******************************************************************************
7729 ** Set the specified signal which is owned by a process to signaled state.
7734 ** Pointer to an gckOS object.
7737 ** Pointer to the gctSIGNAL.
7739 ** gctHANDLE Process
7740 ** Handle of process owning the signal.
7749 IN gctSIGNAL Signal,
7750 IN gctHANDLE Process
7756 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7757 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7759 /* Map the signal into kernel space. */
7760 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7763 status = gckOS_Signal(Os, signal, gcvTRUE);
7765 /* Unmap the signal */
7766 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7772 /* Return the status. */
7777 /*******************************************************************************
7781 ** Wait for a signal to become signaled.
7786 ** Pointer to an gckOS object.
7789 ** Pointer to the gctSIGNAL.
7792 ** Number of milliseconds to wait.
7793 ** Pass the value of gcvINFINITE for an infinite wait.
7802 IN gctSIGNAL Signal,
7806 gceSTATUS status = gcvSTATUS_OK;
7807 gcsSIGNAL_PTR signal;
7809 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7811 /* Verify the arguments. */
7812 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7813 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7815 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7817 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7821 spin_lock_irq(&signal->obj.wait.lock);
7823 if (signal->obj.done)
7825 if (!signal->manualReset)
7827 signal->obj.done = 0;
7830 status = gcvSTATUS_OK;
7834 status = gcvSTATUS_TIMEOUT;
7838 /* Convert wait to milliseconds. */
7839 #if gcdDETECT_TIMEOUT
7840 gctINT timeout = (Wait == gcvINFINITE)
7841 ? gcdINFINITE_TIMEOUT * HZ / 1000
7844 gctUINT complained = 0;
7846 gctINT timeout = (Wait == gcvINFINITE)
7847 ? MAX_SCHEDULE_TIMEOUT
7851 DECLARE_WAITQUEUE(wait, current);
7852 wait.flags |= WQ_FLAG_EXCLUSIVE;
7853 __add_wait_queue_tail(&signal->obj.wait, &wait);
7857 if (signal_pending(current))
7859 /* Interrupt received. */
7860 status = gcvSTATUS_INTERRUPTED;
7864 __set_current_state(TASK_INTERRUPTIBLE);
7865 spin_unlock_irq(&signal->obj.wait.lock);
7866 timeout = schedule_timeout(timeout);
7867 spin_lock_irq(&signal->obj.wait.lock);
7869 if (signal->obj.done)
7871 if (!signal->manualReset)
7873 signal->obj.done = 0;
7876 status = gcvSTATUS_OK;
7880 #if gcdDETECT_TIMEOUT
7881 if ((Wait == gcvINFINITE) && (timeout == 0))
7883 gctUINT32 dmaAddress1, dmaAddress2;
7884 gctUINT32 dmaState1, dmaState2;
7886 dmaState1 = dmaState2 =
7887 dmaAddress1 = dmaAddress2 = 0;
7889 /* Verify whether DMA is running. */
7890 gcmkVERIFY_OK(_VerifyDMA(
7891 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7894 #if gcdDETECT_DMA_ADDRESS
7895 /* Dump only if DMA appears stuck. */
7897 (dmaAddress1 == dmaAddress2)
7898 #if gcdDETECT_DMA_STATE
7899 && (dmaState1 == dmaState2)
7904 /* Increment complain count. */
7907 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
7910 "%s(%d): signal 0x%X; forced message flush (%d).",
7911 __FUNCTION__, __LINE__, Signal, complained
7914 /* Flush the debug cache. */
7915 gcmkDEBUGFLUSH(dmaAddress2);
7918 /* Reset timeout. */
7919 timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
7926 status = gcvSTATUS_TIMEOUT;
7931 __remove_wait_queue(&signal->obj.wait, &wait);
7933 #if gcdDETECT_TIMEOUT
7937 "%s(%d): signal=0x%X; waiting done; status=%d",
7938 __FUNCTION__, __LINE__, Signal, status
7944 spin_unlock_irq(&signal->obj.wait.lock);
7947 /* Return status. */
7948 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7952 /*******************************************************************************
7956 ** Map a signal in to the current process space.
7961 ** Pointer to an gckOS object.
7964 ** Pointer to tha gctSIGNAL to map.
7966 ** gctHANDLE Process
7967 ** Handle of process owning the signal.
7971 ** gctSIGNAL * MappedSignal
7972 ** Pointer to a variable receiving the mapped gctSIGNAL.
7977 IN gctSIGNAL Signal,
7978 IN gctHANDLE Process,
7979 OUT gctSIGNAL * MappedSignal
7983 gcsSIGNAL_PTR signal;
7984 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7986 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7987 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7989 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7991 if(atomic_inc_return(&signal->ref) <= 1)
7993 /* The previous value is 0, it has been deleted. */
7994 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7997 *MappedSignal = (gctSIGNAL) Signal;
8000 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
8001 return gcvSTATUS_OK;
8008 /*******************************************************************************
8010 ** gckOS_UnmapSignal
8017 ** Pointer to an gckOS object.
8020 ** Pointer to that gctSIGNAL mapped.
8028 return gckOS_DestroySignal(Os, Signal);
8031 /*******************************************************************************
8033 ** gckOS_CreateUserSignal
8035 ** Create a new signal to be used in the user space.
8040 ** Pointer to an gckOS object.
8042 ** gctBOOL ManualReset
8043 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
8044 ** order to set the signal to nonsignaled state.
8045 ** If set to gcvFALSE, the signal will automatically be set to
8046 ** nonsignaled state by gckOS_WaitSignal function.
8050 ** gctINT * SignalID
8051 ** Pointer to a variable receiving the created signal's ID.
8054 gckOS_CreateUserSignal(
8056 IN gctBOOL ManualReset,
8057 OUT gctINT * SignalID
8063 /* Create a new signal. */
8064 status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
8065 *SignalID = (gctINT) signal;
8070 /*******************************************************************************
8072 ** gckOS_DestroyUserSignal
8074 ** Destroy a signal to be used in the user space.
8079 ** Pointer to an gckOS object.
8089 gckOS_DestroyUserSignal(
8094 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
8097 /*******************************************************************************
8099 ** gckOS_WaitUserSignal
8101 ** Wait for a signal used in the user mode to become signaled.
8106 ** Pointer to an gckOS object.
8112 ** Number of milliseconds to wait.
8113 ** Pass the value of gcvINFINITE for an infinite wait.
8120 gckOS_WaitUserSignal(
8126 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
8129 /*******************************************************************************
8131 ** gckOS_SignalUserSignal
8133 ** Set a state of the specified signal to be used in the user space.
8138 ** Pointer to an gckOS object.
8144 ** If gcvTRUE, the signal will be set to signaled state.
8145 ** If gcvFALSE, the signal will be set to nonsignaled state.
8152 gckOS_SignalUserSignal(
8158 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
8163 gckOS_CreateSemaphoreVG(
8165 OUT gctSEMAPHORE * Semaphore
8169 struct semaphore * newSemaphore;
8171 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8172 /* Verify the arguments. */
8173 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8174 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8178 /* Allocate the semaphore structure. */
8179 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
8180 if (newSemaphore == gcvNULL)
8182 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
8185 /* Initialize the semaphore. */
8186 sema_init(newSemaphore, 0);
8188 /* Set the handle. */
8189 * Semaphore = (gctSEMAPHORE) newSemaphore;
8192 status = gcvSTATUS_OK;
8197 /* Return the status. */
8203 gckOS_IncrementSemaphore(
8205 IN gctSEMAPHORE Semaphore
8208 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8209 /* Verify the arguments. */
8210 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8211 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8213 /* Increment the semaphore's count. */
8214 up((struct semaphore *) Semaphore);
8218 return gcvSTATUS_OK;
8222 gckOS_DecrementSemaphore(
8224 IN gctSEMAPHORE Semaphore
8230 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8231 /* Verify the arguments. */
8232 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8233 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8237 /* Decrement the semaphore's count. If the count is zero, wait
8238 until it gets incremented. */
8239 result = down_interruptible((struct semaphore *) Semaphore);
8241 /* Signal received? */
8244 status = gcvSTATUS_TERMINATE;
8249 status = gcvSTATUS_OK;
8254 /* Return the status. */
8258 /*******************************************************************************
8262 ** Set the specified signal to signaled state.
8267 ** Pointer to the gckOS object.
8269 ** gctHANDLE Process
8270 ** Handle of process owning the signal.
8273 ** Pointer to the gctSIGNAL.
8282 IN gctHANDLE Process,
8288 struct task_struct * userTask;
8289 struct siginfo info;
8291 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
8293 if (userTask != gcvNULL)
8296 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
8299 info.si_ptr = (gctPOINTER) Signal;
8301 /* Signals with numbers between 32 and 63 are real-time,
8302 send a real-time signal to the user process. */
8303 result = send_sig_info(48, &info, userTask);
8308 status = gcvSTATUS_GENERIC_IO;
8312 "%s(%d): an error has occurred.\n",
8313 __FUNCTION__, __LINE__
8318 status = gcvSTATUS_OK;
8323 status = gcvSTATUS_GENERIC_IO;
8327 "%s(%d): an error has occurred.\n",
8328 __FUNCTION__, __LINE__
8332 /* Return status. */
8336 /******************************************************************************\
8337 ******************************** Thread Object *********************************
8338 \******************************************************************************/
8343 IN gctTHREADFUNC ThreadFunction,
8344 IN gctPOINTER ThreadParameter,
8345 OUT gctTHREAD * Thread
8349 struct task_struct * thread;
8351 gcmkHEADER_ARG("Os=0x%X ", Os);
8352 /* Verify the arguments. */
8353 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8354 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
8355 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8359 /* Create the thread. */
8360 thread = kthread_create(
8363 "Vivante Kernel Thread"
8369 status = gcvSTATUS_GENERIC_IO;
8373 /* Start the thread. */
8374 wake_up_process(thread);
8376 /* Set the thread handle. */
8377 * Thread = (gctTHREAD) thread;
8380 status = gcvSTATUS_OK;
8385 /* Return the status. */
8395 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8396 /* Verify the arguments. */
8397 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8398 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8400 /* Thread should have already been enabled to terminate. */
8401 kthread_stop((struct task_struct *) Thread);
8405 return gcvSTATUS_OK;
8414 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8415 /* Verify the arguments. */
8416 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8417 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8421 return gcvSTATUS_OK;
8425 /******************************************************************************\
8426 ******************************** Software Timer ********************************
8427 \******************************************************************************/
8431 struct work_struct * work
8434 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
8436 gctTIMERFUNCTION function = timer->function;
8438 function(timer->data);
8441 /*******************************************************************************
8443 ** gckOS_CreateTimer
8445 ** Create a software timer.
8450 ** Pointer to the gckOS object.
8452 ** gctTIMERFUNCTION Function.
8453 ** Pointer to a call back function which will be called when timer is
8457 ** Private data which will be passed to call back function.
8461 ** gctPOINTER * Timer
8462 ** Pointer to a variable receiving the created timer.
8467 IN gctTIMERFUNCTION Function,
8469 OUT gctPOINTER * Timer
8473 gcsOSTIMER_PTR pointer;
8474 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
8476 /* Verify the arguments. */
8477 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8478 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8480 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
8482 pointer->function = Function;
8483 pointer->data = Data;
8485 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
8490 return gcvSTATUS_OK;
8497 /*******************************************************************************
8499 ** gckOS_DestroyTimer
8501 ** Destory a software timer.
8506 ** Pointer to the gckOS object.
8509 ** Pointer to the timer to be destoryed.
8521 gcsOSTIMER_PTR timer;
8522 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8524 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8525 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8527 timer = (gcsOSTIMER_PTR)Timer;
8529 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8530 cancel_delayed_work_sync(&timer->work);
8532 cancel_delayed_work(&timer->work);
8533 flush_workqueue(Os->workqueue);
8536 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8539 return gcvSTATUS_OK;
8542 /*******************************************************************************
8546 ** Schedule a software timer.
8551 ** Pointer to the gckOS object.
8554 ** Pointer to the timer to be scheduled.
8557 ** Delay in milliseconds.
8566 IN gctPOINTER Timer,
8570 gcsOSTIMER_PTR timer;
8572 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8574 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8575 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8576 gcmkVERIFY_ARGUMENT(Delay != 0);
8578 timer = (gcsOSTIMER_PTR)Timer;
8580 if (unlikely(delayed_work_pending(&timer->work)))
8582 if (unlikely(!cancel_delayed_work(&timer->work)))
8584 cancel_work_sync(&timer->work.work);
8586 if (unlikely(delayed_work_pending(&timer->work)))
8588 gckOS_Print("gckOS_StartTimer error, the pending worker cannot complete!!!! \n");
8590 return gcvSTATUS_INVALID_REQUEST;
8595 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8598 return gcvSTATUS_OK;
8601 /*******************************************************************************
8605 ** Cancel a unscheduled timer.
8610 ** Pointer to the gckOS object.
8613 ** Pointer to the timer to be cancel.
8625 gcsOSTIMER_PTR timer;
8626 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8628 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8629 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8631 timer = (gcsOSTIMER_PTR)Timer;
8633 cancel_delayed_work(&timer->work);
8636 return gcvSTATUS_OK;
8641 gckOS_DumpCallStack(
8645 gcmkHEADER_ARG("Os=0x%X", Os);
8647 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8652 return gcvSTATUS_OK;
8657 gckOS_GetProcessNameByPid(
8659 IN gctSIZE_T Length,
8660 OUT gctUINT8_PTR String
8663 struct task_struct *task;
8665 /* Get the task_struct of the task with pid. */
8668 task = FIND_TASK_BY_PID(Pid);
8670 if (task == gcvNULL)
8673 return gcvSTATUS_NOT_FOUND;
8676 /* Get name of process. */
8677 strncpy(String, task->comm, Length);
8681 return gcvSTATUS_OK;
8684 #if gcdANDROID_NATIVE_FENCE_SYNC
8687 gckOS_CreateSyncPoint(
8689 OUT gctSYNC_POINT * SyncPoint
8693 gcsSYNC_POINT_PTR syncPoint;
8695 gcmkHEADER_ARG("Os=0x%X", Os);
8697 /* Verify the arguments. */
8698 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8700 /* Create an sync point structure. */
8701 syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
8702 sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
8704 if (syncPoint == gcvNULL)
8706 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8709 /* Initialize the sync point. */
8710 atomic_set(&syncPoint->ref, 1);
8711 atomic_set(&syncPoint->state, 0);
8713 gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
8715 *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
8717 gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
8718 return gcvSTATUS_OK;
8721 if (syncPoint != gcvNULL)
8731 gckOS_ReferenceSyncPoint(
8733 IN gctSYNC_POINT SyncPoint
8737 gcsSYNC_POINT_PTR syncPoint;
8739 gcmkHEADER_ARG("Os=0x%X", Os);
8741 /* Verify the arguments. */
8742 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8743 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8746 _QueryIntegerId(&Os->syncPointDB,
8747 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8748 (gctPOINTER)&syncPoint));
8750 /* Initialize the sync point. */
8751 atomic_inc(&syncPoint->ref);
8754 return gcvSTATUS_OK;
8762 gckOS_DestroySyncPoint(
8764 IN gctSYNC_POINT SyncPoint
8768 gcsSYNC_POINT_PTR syncPoint;
8769 gctBOOL acquired = gcvFALSE;
8771 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8773 /* Verify the arguments. */
8774 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8775 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8777 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8781 _QueryIntegerId(&Os->syncPointDB,
8782 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8783 (gctPOINTER)&syncPoint));
8785 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8787 if (atomic_dec_and_test(&syncPoint->ref))
8789 gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
8791 /* Free the sgianl. */
8792 syncPoint->timeline = gcvNULL;
8796 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8797 acquired = gcvFALSE;
8801 return gcvSTATUS_OK;
8806 /* Release the mutex. */
8807 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8815 gckOS_SignalSyncPoint(
8817 IN gctSYNC_POINT SyncPoint
8821 gcsSYNC_POINT_PTR syncPoint;
8822 gctBOOL acquired = gcvFALSE;
8824 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8826 /* Verify the arguments. */
8827 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8828 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8830 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8834 _QueryIntegerId(&Os->syncPointDB,
8835 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8836 (gctPOINTER)&syncPoint));
8838 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8841 atomic_set(&syncPoint->state, gcvTRUE);
8843 /* Signal timeline. */
8844 if (syncPoint->timeline)
8846 sync_timeline_signal(syncPoint->timeline);
8849 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8850 acquired = gcvFALSE;
8854 return gcvSTATUS_OK;
8859 /* Release the mutex. */
8860 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8868 gckOS_QuerySyncPoint(
8870 IN gctSYNC_POINT SyncPoint,
8871 OUT gctBOOL_PTR State
8875 gcsSYNC_POINT_PTR syncPoint;
8877 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8879 /* Verify the arguments. */
8880 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8881 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8884 _QueryIntegerId(&Os->syncPointDB,
8885 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8886 (gctPOINTER)&syncPoint));
8888 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8891 *State = atomic_read(&syncPoint->state);
8894 gcmkFOOTER_ARG("*State=%d", *State);
8895 return gcvSTATUS_OK;
8903 gckOS_CreateSyncTimeline(
8905 OUT gctHANDLE * Timeline
8908 struct viv_sync_timeline * timeline;
8910 /* Create viv sync timeline. */
8911 timeline = viv_sync_timeline_create("viv timeline", Os);
8913 if (timeline == gcvNULL)
8915 /* Out of memory. */
8916 return gcvSTATUS_OUT_OF_MEMORY;
8919 *Timeline = (gctHANDLE) timeline;
8920 return gcvSTATUS_OK;
8924 gckOS_DestroySyncTimeline(
8926 IN gctHANDLE Timeline
8929 struct viv_sync_timeline * timeline;
8930 gcmkASSERT(Timeline != gcvNULL);
8932 /* Destroy timeline. */
8933 timeline = (struct viv_sync_timeline *) Timeline;
8934 sync_timeline_destroy(&timeline->obj);
8936 return gcvSTATUS_OK;
8940 gckOS_CreateNativeFence(
8942 IN gctHANDLE Timeline,
8943 IN gctSYNC_POINT SyncPoint,
8944 OUT gctINT * FenceFD
8948 struct viv_sync_timeline *timeline;
8949 struct sync_pt * pt = gcvNULL;
8950 struct sync_fence * fence;
8952 gcsSYNC_POINT_PTR syncPoint;
8955 gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
8956 Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
8959 _QueryIntegerId(&Os->syncPointDB,
8960 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8961 (gctPOINTER)&syncPoint));
8963 /* Cast timeline. */
8964 timeline = (struct viv_sync_timeline *) Timeline;
8966 fd = get_unused_fd();
8970 /* Out of resources. */
8971 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
8974 /* Create viv_sync_pt. */
8975 pt = viv_sync_pt_create(timeline, SyncPoint);
8979 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8982 /* Reference sync_timeline. */
8983 syncPoint->timeline = &timeline->obj;
8985 /* Build fence name. */
8986 snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
8988 /* Create sync_fence. */
8989 fence = sync_fence_create(name, pt);
8993 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8996 /* Install fence to fd. */
8997 sync_fence_install(fence, fd);
9000 gcmkFOOTER_ARG("*FenceFD=%d", fd);
9001 return gcvSTATUS_OK;
9004 /* Error roll back. */