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);
2022 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2025 /*Free all cache and try again*/
2026 _FreeAllNonPagedMemoryCache(Os);
2027 addr = dma_alloc_coherent(gcvNULL,
2028 mdl->numPages * PAGE_SIZE,
2030 GFP_KERNEL | gcdNOWARN);
2034 size = mdl->numPages * PAGE_SIZE;
2035 order = get_order(size);
2036 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2037 page = _GetNonPagedMemoryCache(Os, order);
2039 if (page == gcvNULL)
2042 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
2045 if (page == gcvNULL)
2047 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2050 vaddr = (gctPOINTER)page_address(page);
2051 mdl->contiguous = gcvTRUE;
2052 mdl->u.contiguousPages = page;
2053 addr = _CreateKernelVirtualMapping(mdl);
2054 mdl->dmaHandle = virt_to_phys(vaddr);
2056 mdl->u.contiguousPages = page;
2058 #if !defined(CONFIG_PPC)
2059 /* Cache invalidate. */
2060 dma_sync_single_for_device(
2069 SetPageReserved(virt_to_page(vaddr));
2076 if (addr == gcvNULL)
2078 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2083 /* Return allocated memory. */
2085 *Physical = (gctPHYS_ADDR) mdl;
2089 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
2091 if (mdlMap == gcvNULL)
2093 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2096 /* Only after mmap this will be valid. */
2098 /* We need to map this to user space. */
2099 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2100 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
2102 mdl->numPages * PAGE_SIZE,
2103 PROT_READ | PROT_WRITE,
2107 down_write(¤t->mm->mmap_sem);
2109 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
2111 mdl->numPages * PAGE_SIZE,
2112 PROT_READ | PROT_WRITE,
2116 up_write(¤t->mm->mmap_sem);
2119 if (IS_ERR(mdlMap->vmaAddr))
2122 gcvLEVEL_WARNING, gcvZONE_OS,
2123 "%s(%d): do_mmap_pgoff error",
2124 __FUNCTION__, __LINE__
2127 mdlMap->vmaAddr = gcvNULL;
2129 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2132 down_write(¤t->mm->mmap_sem);
2134 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
2136 if (mdlMap->vma == gcvNULL)
2139 gcvLEVEL_WARNING, gcvZONE_OS,
2140 "%s(%d): find_vma error",
2141 __FUNCTION__, __LINE__
2144 up_write(¤t->mm->mmap_sem);
2146 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2149 #ifndef NO_DMA_COHERENT
2150 if (dma_mmap_coherent(gcvNULL,
2154 mdl->numPages * PAGE_SIZE) < 0)
2157 gcvLEVEL_WARNING, gcvZONE_OS,
2158 "%s(%d): dma_mmap_coherent error",
2159 __FUNCTION__, __LINE__
2162 up_write(¤t->mm->mmap_sem);
2164 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2167 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
2168 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
2169 mdlMap->vma->vm_pgoff = 0;
2171 if (remap_pfn_range(mdlMap->vma,
2172 mdlMap->vma->vm_start,
2173 mdl->dmaHandle >> PAGE_SHIFT,
2174 mdl->numPages * PAGE_SIZE,
2175 mdlMap->vma->vm_page_prot))
2178 gcvLEVEL_WARNING, gcvZONE_OS,
2179 "%s(%d): remap_pfn_range error",
2180 __FUNCTION__, __LINE__
2183 up_write(¤t->mm->mmap_sem);
2185 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2187 #endif /* NO_DMA_COHERENT */
2189 up_write(¤t->mm->mmap_sem);
2191 *Logical = mdlMap->vmaAddr;
2195 *Logical = (gctPOINTER)mdl->addr;
2199 * Add this to a global list.
2200 * Will be used by get physical address
2201 * and mapuser pointer functions.
2206 /* Initialize the queue. */
2207 Os->mdlHead = Os->mdlTail = mdl;
2211 /* Add to the tail. */
2212 mdl->prev = Os->mdlTail;
2213 Os->mdlTail->next = mdl;
2220 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
2221 *Bytes, *Physical, *Logical);
2222 return gcvSTATUS_OK;
2225 if (mdlMap != gcvNULL)
2227 /* Free LINUX_MDL_MAP. */
2228 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
2233 /* Free LINUX_MDL. */
2234 gcmkVERIFY_OK(_DestroyMdl(mdl));
2239 /* Unlock memory. */
2243 /* Return the status. */
2248 /*******************************************************************************
2250 ** gckOS_FreeNonPagedMemory
2252 ** Free previously allocated and mapped pages from non-paged memory.
2257 ** Pointer to an gckOS object.
2260 ** Number of bytes allocated.
2262 ** gctPHYS_ADDR Physical
2263 ** Physical address of the allocated memory.
2265 ** gctPOINTER Logical
2266 ** Logical address of the allocated memory.
2272 gceSTATUS gckOS_FreeNonPagedMemory(
2275 IN gctPHYS_ADDR Physical,
2276 IN gctPOINTER Logical
2280 PLINUX_MDL_MAP mdlMap;
2281 #ifdef NO_DMA_COHERENT
2284 #endif /* NO_DMA_COHERENT */
2286 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
2287 Os, Bytes, Physical, Logical);
2289 /* Verify the arguments. */
2290 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2291 gcmkVERIFY_ARGUMENT(Bytes > 0);
2292 gcmkVERIFY_ARGUMENT(Physical != 0);
2293 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2295 /* Convert physical address into a pointer to a MDL. */
2296 mdl = (PLINUX_MDL) Physical;
2300 #ifndef NO_DMA_COHERENT
2301 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2302 if (!_AddNonPagedMemoryCache(Os,
2303 mdl->numPages * PAGE_SIZE,
2308 dma_free_coherent(gcvNULL,
2309 mdl->numPages * PAGE_SIZE,
2314 size = mdl->numPages * PAGE_SIZE;
2319 ClearPageReserved(virt_to_page(vaddr));
2325 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2326 if (!_AddNonPagedMemoryCache(Os,
2327 get_order(mdl->numPages * PAGE_SIZE),
2328 virt_to_page(mdl->kaddr)))
2331 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
2334 _DestoryKernelVirtualMapping(mdl->addr);
2335 #endif /* NO_DMA_COHERENT */
2339 while (mdlMap != gcvNULL)
2341 if (mdlMap->vmaAddr != gcvNULL)
2343 /* No mapped memory exists when free nonpaged memory */
2347 mdlMap = mdlMap->next;
2350 /* Remove the node from global list.. */
2351 if (mdl == Os->mdlHead)
2353 if ((Os->mdlHead = mdl->next) == gcvNULL)
2355 Os->mdlTail = gcvNULL;
2360 mdl->prev->next = mdl->next;
2361 if (mdl == Os->mdlTail)
2363 Os->mdlTail = mdl->prev;
2367 mdl->next->prev = mdl->prev;
2373 gcmkVERIFY_OK(_DestroyMdl(mdl));
2377 return gcvSTATUS_OK;
2380 /*******************************************************************************
2382 ** gckOS_ReadRegister
2384 ** Read data from a register.
2389 ** Pointer to an gckOS object.
2391 ** gctUINT32 Address
2392 ** Address of register.
2397 ** Pointer to a variable that receives the data read from the register.
2402 IN gctUINT32 Address,
2403 OUT gctUINT32 * Data
2406 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2410 gckOS_ReadRegisterEx(
2413 IN gctUINT32 Address,
2414 OUT gctUINT32 * Data
2417 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
2419 /* Verify the arguments. */
2420 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2421 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2422 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2424 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
2427 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2428 return gcvSTATUS_OK;
2431 /*******************************************************************************
2433 ** gckOS_WriteRegister
2435 ** Write data to a register.
2440 ** Pointer to an gckOS object.
2442 ** gctUINT32 Address
2443 ** Address of register.
2446 ** Data for register.
2453 gckOS_WriteRegister(
2455 IN gctUINT32 Address,
2459 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2463 gckOS_WriteRegisterEx(
2466 IN gctUINT32 Address,
2470 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2472 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2474 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2478 return gcvSTATUS_OK;
2481 /*******************************************************************************
2483 ** gckOS_GetPageSize
2485 ** Get the system's page size.
2490 ** Pointer to an gckOS object.
2494 ** gctSIZE_T * PageSize
2495 ** Pointer to a variable that will receive the system's page size.
2497 gceSTATUS gckOS_GetPageSize(
2499 OUT gctSIZE_T * PageSize
2502 gcmkHEADER_ARG("Os=0x%X", Os);
2504 /* Verify the arguments. */
2505 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2506 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2508 /* Return the page size. */
2509 *PageSize = (gctSIZE_T) PAGE_SIZE;
2512 gcmkFOOTER_ARG("*PageSize", *PageSize);
2513 return gcvSTATUS_OK;
2516 /*******************************************************************************
2518 ** gckOS_GetPhysicalAddress
2520 ** Get the physical system address of a corresponding virtual address.
2525 ** Pointer to an gckOS object.
2527 ** gctPOINTER Logical
2532 ** gctUINT32 * Address
2533 ** Poinetr to a variable that receives the 32-bit physical adress.
2536 gckOS_GetPhysicalAddress(
2538 IN gctPOINTER Logical,
2539 OUT gctUINT32 * Address
2543 gctUINT32 processID;
2545 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2547 /* Verify the arguments. */
2548 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2549 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2551 /* Query page table of current process first. */
2552 status = _QueryProcessPageTable(Logical, Address);
2554 if (gcmIS_ERROR(status))
2556 /* Get current process ID. */
2557 processID = _GetProcessID();
2559 /* Route through other function. */
2561 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2565 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2566 return gcvSTATUS_OK;
2569 /* Return the status. */
2578 IN gctUINT32 Physical,
2579 IN gctPOINTER Logical,
2584 gcsUSER_MAPPING_PTR map;
2586 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2587 Os, Physical, Logical, Bytes);
2589 gcmkONERROR(gckOS_Allocate(Os,
2590 gcmSIZEOF(gcsUSER_MAPPING),
2591 (gctPOINTER *) &map));
2593 map->next = Os->userMap;
2594 map->physical = Physical - Os->device->baseAddress;
2595 map->logical = Logical;
2597 map->start = (gctINT8_PTR) Logical;
2598 map->end = map->start + Bytes;
2603 return gcvSTATUS_OK;
2611 gckOS_RemoveMapping(
2613 IN gctPOINTER Logical,
2618 gcsUSER_MAPPING_PTR map, prev;
2620 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2622 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2624 if ((map->logical == Logical)
2625 && (map->bytes == Bytes)
2636 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2639 if (prev == gcvNULL)
2641 Os->userMap = map->next;
2645 prev->next = map->next;
2648 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2651 return gcvSTATUS_OK;
2660 _ConvertLogical2Physical(
2662 IN gctPOINTER Logical,
2663 IN gctUINT32 ProcessID,
2665 OUT gctUINT32_PTR Physical
2668 gctINT8_PTR base, vBase;
2671 gcsUSER_MAPPING_PTR userMap;
2673 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2675 /* Check for the logical address match. */
2676 if ((base != gcvNULL)
2677 && ((gctINT8_PTR) Logical >= base)
2678 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2681 offset = (gctINT8_PTR) Logical - base;
2683 if (Mdl->dmaHandle != 0)
2685 /* The memory was from coherent area. */
2686 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2688 else if (Mdl->pagedMem && !Mdl->contiguous)
2690 /* paged memory is not mapped to kernel space. */
2691 return gcvSTATUS_INVALID_ADDRESS;
2695 *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
2698 return gcvSTATUS_OK;
2701 /* Walk user maps. */
2702 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2704 if (((gctINT8_PTR) Logical >= userMap->start)
2705 && ((gctINT8_PTR) Logical < userMap->end)
2708 *Physical = userMap->physical
2709 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2711 return gcvSTATUS_OK;
2715 if (ProcessID != Os->kernelProcessID)
2717 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2718 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2720 /* Is the given address within that range. */
2721 if ((vBase != gcvNULL)
2722 && ((gctINT8_PTR) Logical >= vBase)
2723 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2726 offset = (gctINT8_PTR) Logical - vBase;
2728 if (Mdl->dmaHandle != 0)
2730 /* The memory was from coherent area. */
2731 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2733 else if (Mdl->pagedMem && !Mdl->contiguous)
2735 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2739 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2742 return gcvSTATUS_OK;
2746 /* Address not yet found. */
2747 return gcvSTATUS_INVALID_ADDRESS;
2750 /*******************************************************************************
2752 ** gckOS_GetPhysicalAddressProcess
2754 ** Get the physical system address of a corresponding virtual address for a
2760 ** Pointer to gckOS object.
2762 ** gctPOINTER Logical
2765 ** gctUINT32 ProcessID
2770 ** gctUINT32 * Address
2771 ** Poinetr to a variable that receives the 32-bit physical adress.
2774 gckOS_GetPhysicalAddressProcess(
2776 IN gctPOINTER Logical,
2777 IN gctUINT32 ProcessID,
2778 OUT gctUINT32 * Address
2783 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2785 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2787 /* Verify the arguments. */
2788 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2789 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2793 /* First try the contiguous memory pool. */
2794 if (Os->device->contiguousMapped)
2796 base = (gctINT8_PTR) Os->device->contiguousBase;
2798 if (((gctINT8_PTR) Logical >= base)
2799 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2802 /* Convert logical address into physical. */
2803 *Address = Os->device->contiguousVidMem->baseAddress
2804 + (gctINT8_PTR) Logical - base;
2805 status = gcvSTATUS_OK;
2810 /* Try the contiguous memory pool. */
2811 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2812 status = _ConvertLogical2Physical(Os,
2819 if (gcmIS_ERROR(status))
2821 /* Walk all MDLs. */
2822 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2825 status = _ConvertLogical2Physical(Os,
2830 if (gcmIS_SUCCESS(status))
2839 gcmkONERROR(status);
2842 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2843 return gcvSTATUS_OK;
2846 /* Return the status. */
2851 /*******************************************************************************
2853 ** gckOS_MapPhysical
2855 ** Map a physical address into kernel space.
2860 ** Pointer to an gckOS object.
2862 ** gctUINT32 Physical
2863 ** Physical address of the memory to map.
2866 ** Number of bytes to map.
2870 ** gctPOINTER * Logical
2871 ** Pointer to a variable that receives the base address of the mapped
2877 IN gctUINT32 Physical,
2879 OUT gctPOINTER * Logical
2884 gctUINT32 physical = Physical;
2886 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2888 /* Verify the arguments. */
2889 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2890 gcmkVERIFY_ARGUMENT(Bytes > 0);
2891 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2895 /* Go through our mapping to see if we know this physical address already. */
2898 while (mdl != gcvNULL)
2900 if (mdl->dmaHandle != 0)
2902 if ((physical >= mdl->dmaHandle)
2903 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2906 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2916 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2917 struct contiguous_mem_pool *pool = Os->device->pool;
2919 if (Physical >= pool->phys && Physical < pool->phys + pool->size)
2920 logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
2924 /* Map memory as cached memory. */
2925 request_mem_region(physical, Bytes, "MapRegion");
2926 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2929 if (logical == gcvNULL)
2932 gcvLEVEL_INFO, gcvZONE_OS,
2933 "%s(%d): Failed to map physical address 0x%08x",
2934 __FUNCTION__, __LINE__, Physical
2939 /* Out of resources. */
2940 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2941 return gcvSTATUS_OUT_OF_RESOURCES;
2944 /* Return pointer to mapped memory. */
2951 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2952 return gcvSTATUS_OK;
2955 /*******************************************************************************
2957 ** gckOS_UnmapPhysical
2959 ** Unmap a previously mapped memory region from kernel memory.
2964 ** Pointer to an gckOS object.
2966 ** gctPOINTER Logical
2967 ** Pointer to the base address of the memory to unmap.
2970 ** Number of bytes to unmap.
2977 gckOS_UnmapPhysical(
2979 IN gctPOINTER Logical,
2985 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2987 /* Verify the arguments. */
2988 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2989 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2990 gcmkVERIFY_ARGUMENT(Bytes > 0);
2996 while (mdl != gcvNULL)
2998 if (mdl->addr != gcvNULL)
3000 if (Logical >= (gctPOINTER)mdl->addr
3001 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
3012 /* Unmap the memory. */
3020 return gcvSTATUS_OK;
3023 /*******************************************************************************
3025 ** gckOS_CreateMutex
3027 ** Create a new mutex.
3032 ** Pointer to an gckOS object.
3036 ** gctPOINTER * Mutex
3037 ** Pointer to a variable that will hold a pointer to the mutex.
3042 OUT gctPOINTER * Mutex
3047 gcmkHEADER_ARG("Os=0x%X", Os);
3049 /* Validate the arguments. */
3050 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3051 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3053 /* Allocate the mutex structure. */
3054 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
3056 /* Initialize the mutex. */
3059 /* Return status. */
3060 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
3061 return gcvSTATUS_OK;
3064 /* Return status. */
3069 /*******************************************************************************
3071 ** gckOS_DeleteMutex
3078 ** Pointer to an gckOS object.
3081 ** Pointer to the mute to be deleted.
3095 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
3097 /* Validate the arguments. */
3098 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3099 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3101 /* Destroy the mutex. */
3102 mutex_destroy(Mutex);
3104 /* Free the mutex structure. */
3105 gcmkONERROR(gckOS_Free(Os, Mutex));
3108 return gcvSTATUS_OK;
3111 /* Return status. */
3116 /*******************************************************************************
3118 ** gckOS_AcquireMutex
3125 ** Pointer to an gckOS object.
3128 ** Pointer to the mutex to be acquired.
3130 ** gctUINT32 Timeout
3131 ** Timeout value specified in milliseconds.
3132 ** Specify the value of gcvINFINITE to keep the thread suspended
3133 ** until the mutex has been acquired.
3142 IN gctPOINTER Mutex,
3143 IN gctUINT32 Timeout
3146 #if gcdDETECT_TIMEOUT
3150 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
3152 /* Validate the arguments. */
3153 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3154 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3156 #if gcdDETECT_TIMEOUT
3161 /* Try to acquire the mutex. */
3162 if (mutex_trylock(Mutex))
3166 return gcvSTATUS_OK;
3169 /* Advance the timeout. */
3172 if (Timeout == gcvINFINITE)
3174 if (timeout == gcdINFINITE_TIMEOUT)
3176 gctUINT32 dmaAddress1, dmaAddress2;
3177 gctUINT32 dmaState1, dmaState2;
3179 dmaState1 = dmaState2 =
3180 dmaAddress1 = dmaAddress2 = 0;
3182 /* Verify whether DMA is running. */
3183 gcmkVERIFY_OK(_VerifyDMA(
3184 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
3187 #if gcdDETECT_DMA_ADDRESS
3188 /* Dump only if DMA appears stuck. */
3190 (dmaAddress1 == dmaAddress2)
3191 #if gcdDETECT_DMA_STATE
3192 && (dmaState1 == dmaState2)
3197 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
3200 "%s(%d): mutex 0x%X; forced message flush.",
3201 __FUNCTION__, __LINE__, Mutex
3204 /* Flush the debug cache. */
3205 gcmkDEBUGFLUSH(dmaAddress2);
3214 if (timeout >= Timeout)
3220 /* Wait for 1 millisecond. */
3221 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3224 if (Timeout == gcvINFINITE)
3226 /* Lock the mutex. */
3231 return gcvSTATUS_OK;
3236 /* Try to acquire the mutex. */
3237 if (mutex_trylock(Mutex))
3241 return gcvSTATUS_OK;
3249 /* Wait for 1 millisecond. */
3250 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3255 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
3256 return gcvSTATUS_TIMEOUT;
3259 /*******************************************************************************
3261 ** gckOS_ReleaseMutex
3263 ** Release an acquired mutex.
3268 ** Pointer to an gckOS object.
3271 ** Pointer to the mutex to be released.
3283 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
3285 /* Validate the arguments. */
3286 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3287 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3289 /* Release the mutex. */
3290 mutex_unlock(Mutex);
3294 return gcvSTATUS_OK;
3297 /*******************************************************************************
3299 ** gckOS_AtomicExchange
3301 ** Atomically exchange a pair of 32-bit values.
3306 ** Pointer to an gckOS object.
3308 ** IN OUT gctINT32_PTR Target
3309 ** Pointer to the 32-bit value to exchange.
3311 ** IN gctINT32 NewValue
3312 ** Specifies a new value for the 32-bit value pointed to by Target.
3314 ** OUT gctINT32_PTR OldValue
3315 ** The old value of the 32-bit value pointed to by Target.
3322 gckOS_AtomicExchange(
3324 IN OUT gctUINT32_PTR Target,
3325 IN gctUINT32 NewValue,
3326 OUT gctUINT32_PTR OldValue
3329 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
3331 /* Verify the arguments. */
3332 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3334 /* Exchange the pair of 32-bit values. */
3335 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
3338 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
3339 return gcvSTATUS_OK;
3342 /*******************************************************************************
3344 ** gckOS_AtomicExchangePtr
3346 ** Atomically exchange a pair of pointers.
3351 ** Pointer to an gckOS object.
3353 ** IN OUT gctPOINTER * Target
3354 ** Pointer to the 32-bit value to exchange.
3356 ** IN gctPOINTER NewValue
3357 ** Specifies a new value for the pointer pointed to by Target.
3359 ** OUT gctPOINTER * OldValue
3360 ** The old value of the pointer pointed to by Target.
3367 gckOS_AtomicExchangePtr(
3369 IN OUT gctPOINTER * Target,
3370 IN gctPOINTER NewValue,
3371 OUT gctPOINTER * OldValue
3374 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3376 /* Verify the arguments. */
3377 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3379 /* Exchange the pair of pointers. */
3380 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3383 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3384 return gcvSTATUS_OK;
3388 /*******************************************************************************
3390 ** gckOS_AtomicSetMask
3392 ** Atomically set mask to Atom
3395 ** IN OUT gctPOINTER Atom
3396 ** Pointer to the atom to set.
3398 ** IN gctUINT32 Mask
3411 gctUINT32 oval, nval;
3413 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3414 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3418 oval = atomic_read((atomic_t *) Atom);
3420 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3423 return gcvSTATUS_OK;
3426 /*******************************************************************************
3428 ** gckOS_AtomClearMask
3430 ** Atomically clear mask from Atom
3433 ** IN OUT gctPOINTER Atom
3434 ** Pointer to the atom to clear.
3436 ** IN gctUINT32 Mask
3444 gckOS_AtomClearMask(
3449 gctUINT32 oval, nval;
3451 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3452 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3456 oval = atomic_read((atomic_t *) Atom);
3457 nval = oval & ~Mask;
3458 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3461 return gcvSTATUS_OK;
3465 /*******************************************************************************
3467 ** gckOS_AtomConstruct
3474 ** Pointer to a gckOS object.
3478 ** gctPOINTER * Atom
3479 ** Pointer to a variable receiving the constructed atom.
3482 gckOS_AtomConstruct(
3484 OUT gctPOINTER * Atom
3489 gcmkHEADER_ARG("Os=0x%X", Os);
3491 /* Verify the arguments. */
3492 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3493 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3495 /* Allocate the atom. */
3496 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3498 /* Initialize the atom. */
3499 atomic_set((atomic_t *) *Atom, 0);
3502 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3503 return gcvSTATUS_OK;
3506 /* Return the status. */
3511 /*******************************************************************************
3513 ** gckOS_AtomDestroy
3520 ** Pointer to a gckOS object.
3523 ** Pointer to the atom to destroy.
3537 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3539 /* Verify the arguments. */
3540 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3541 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3543 /* Free the atom. */
3544 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3548 return gcvSTATUS_OK;
3551 /* Return the status. */
3556 /*******************************************************************************
3560 ** Get the 32-bit value protected by an atom.
3565 ** Pointer to a gckOS object.
3568 ** Pointer to the atom.
3572 ** gctINT32_PTR Value
3573 ** Pointer to a variable the receives the value of the atom.
3579 OUT gctINT32_PTR Value
3582 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3584 /* Verify the arguments. */
3585 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3586 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3588 /* Return the current value of atom. */
3589 *Value = atomic_read((atomic_t *) Atom);
3592 gcmkFOOTER_ARG("*Value=%d", *Value);
3593 return gcvSTATUS_OK;
3596 /*******************************************************************************
3600 ** Set the 32-bit value protected by an atom.
3605 ** Pointer to a gckOS object.
3608 ** Pointer to the atom.
3611 ** The value of the atom.
3624 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3626 /* Verify the arguments. */
3627 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3628 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3630 /* Set the current value of atom. */
3631 atomic_set((atomic_t *) Atom, Value);
3635 return gcvSTATUS_OK;
3638 /*******************************************************************************
3640 ** gckOS_AtomIncrement
3642 ** Atomically increment the 32-bit integer value inside an atom.
3647 ** Pointer to a gckOS object.
3650 ** Pointer to the atom.
3654 ** gctINT32_PTR Value
3655 ** Pointer to a variable that receives the original value of the atom.
3658 gckOS_AtomIncrement(
3661 OUT gctINT32_PTR Value
3664 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3666 /* Verify the arguments. */
3667 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3668 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3670 /* Increment the atom. */
3671 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3674 gcmkFOOTER_ARG("*Value=%d", *Value);
3675 return gcvSTATUS_OK;
3678 /*******************************************************************************
3680 ** gckOS_AtomDecrement
3682 ** Atomically decrement the 32-bit integer value inside an atom.
3687 ** Pointer to a gckOS object.
3690 ** Pointer to the atom.
3694 ** gctINT32_PTR Value
3695 ** Pointer to a variable that receives the original value of the atom.
3698 gckOS_AtomDecrement(
3701 OUT gctINT32_PTR Value
3704 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3706 /* Verify the arguments. */
3707 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3708 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3710 /* Decrement the atom. */
3711 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3714 gcmkFOOTER_ARG("*Value=%d", *Value);
3715 return gcvSTATUS_OK;
3718 /*******************************************************************************
3722 ** Delay execution of the current thread for a number of milliseconds.
3727 ** Pointer to an gckOS object.
3730 ** Delay to sleep, specified in milliseconds.
3742 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3746 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3747 ktime_t delay = ktime_set(Delay/1000, (Delay%1000) * NSEC_PER_MSEC);
3748 __set_current_state(TASK_UNINTERRUPTIBLE);
3749 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3758 return gcvSTATUS_OK;
3761 /*******************************************************************************
3765 ** Get the number of milliseconds since the system started.
3771 ** gctUINT32_PTR Time
3772 ** Pointer to a variable to get time.
3777 OUT gctUINT32_PTR Time
3782 *Time = jiffies_to_msecs(jiffies);
3785 return gcvSTATUS_OK;
3788 /*******************************************************************************
3792 ** Compare time values got from gckOS_GetTicks.
3796 ** First time value to be compared.
3799 ** Second time value to be compared.
3803 ** gctBOOL_PTR IsAfter
3804 ** Pointer to a variable to result.
3811 OUT gctBOOL_PTR IsAfter
3816 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3819 return gcvSTATUS_OK;
3822 /*******************************************************************************
3826 ** Get the number of microseconds since the system started.
3832 ** gctUINT64_PTR Time
3833 ** Pointer to a variable to get time.
3838 OUT gctUINT64_PTR Time
3846 return gcvSTATUS_OK;
3849 /*******************************************************************************
3851 ** gckOS_MemoryBarrier
3853 ** Make sure the CPU has executed everything up to this point and the data got
3854 ** written to the specified pointer.
3859 ** Pointer to an gckOS object.
3861 ** gctPOINTER Address
3862 ** Address of memory that needs to be barriered.
3869 gckOS_MemoryBarrier(
3871 IN gctPOINTER Address
3874 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3876 /* Verify the arguments. */
3877 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3879 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3880 && defined (CONFIG_ARM) \
3881 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3882 /* drain write buffer */
3885 /* drain outer cache's write buffer? */
3892 return gcvSTATUS_OK;
3895 /*******************************************************************************
3897 ** gckOS_AllocatePagedMemory
3899 ** Allocate memory from the paged pool.
3904 ** Pointer to an gckOS object.
3907 ** Number of bytes to allocate.
3911 ** gctPHYS_ADDR * Physical
3912 ** Pointer to a variable that receives the physical address of the
3913 ** memory allocation.
3916 gckOS_AllocatePagedMemory(
3919 OUT gctPHYS_ADDR * Physical
3924 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3926 /* Verify the arguments. */
3927 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3928 gcmkVERIFY_ARGUMENT(Bytes > 0);
3929 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3931 /* Allocate the memory. */
3932 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
3935 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3936 return gcvSTATUS_OK;
3939 /* Return the status. */
3944 /*******************************************************************************
3946 ** gckOS_AllocatePagedMemoryEx
3948 ** Allocate memory from the paged pool.
3953 ** Pointer to an gckOS object.
3955 ** gctBOOL Contiguous
3956 ** Need contiguous memory or not.
3959 ** Number of bytes to allocate.
3963 ** gctPHYS_ADDR * Physical
3964 ** Pointer to a variable that receives the physical address of the
3965 ** memory allocation.
3968 gckOS_AllocatePagedMemoryEx(
3970 IN gctBOOL Contiguous,
3972 OUT gctPHYS_ADDR * Physical
3977 PLINUX_MDL mdl = gcvNULL;
3979 gctBOOL locked = gcvFALSE;
3981 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3982 gctPOINTER addr = gcvNULL;
3985 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
3987 /* Verify the arguments. */
3988 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3989 gcmkVERIFY_ARGUMENT(Bytes > 0);
3990 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3992 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3994 numPages = GetPageCount(bytes, 0);
3999 mdl = _CreateMdl(_GetProcessID());
4002 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4007 gctUINT32 order = get_order(bytes);
4009 if (order >= MAX_ORDER)
4011 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4014 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4016 alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
4018 mdl->u.contiguousPages = addr
4019 ? virt_to_page(addr)
4022 mdl->exact = gcvTRUE;
4024 mdl->u.contiguousPages =
4025 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
4027 if (mdl->u.contiguousPages == gcvNULL)
4029 mdl->u.contiguousPages =
4030 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
4032 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4033 mdl->exact = gcvFALSE;
4039 mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
4042 if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
4044 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4049 mdl->numPages = numPages;
4051 mdl->contiguous = Contiguous;
4053 for (i = 0; i < mdl->numPages; i++)
4057 if (mdl->contiguous)
4059 page = nth_page(mdl->u.contiguousPages, i);
4063 page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
4066 SetPageReserved(page);
4068 if (!PageHighMem(page) && page_to_phys(page))
4071 gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
4072 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
4078 /* Return physical address. */
4079 *Physical = (gctPHYS_ADDR) mdl;
4082 * Add this to a global list.
4083 * Will be used by get physical address
4084 * and mapuser pointer functions.
4088 /* Initialize the queue. */
4089 Os->mdlHead = Os->mdlTail = mdl;
4094 mdl->prev = Os->mdlTail;
4095 Os->mdlTail->next = mdl;
4102 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
4103 return gcvSTATUS_OK;
4108 /* Free the memory. */
4114 /* Unlock the memory. */
4118 /* Return the status. */
4123 /*******************************************************************************
4125 ** gckOS_FreePagedMemory
4127 ** Free memory allocated from the paged pool.
4132 ** Pointer to an gckOS object.
4134 ** gctPHYS_ADDR Physical
4135 ** Physical address of the allocation.
4138 ** Number of bytes of the allocation.
4145 gckOS_FreePagedMemory(
4147 IN gctPHYS_ADDR Physical,
4151 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
4154 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
4156 /* Verify the arguments. */
4157 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4158 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4159 gcmkVERIFY_ARGUMENT(Bytes > 0);
4161 /*addr = mdl->addr;*/
4165 for (i = 0; i < mdl->numPages; i++)
4167 if (mdl->contiguous)
4169 ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
4173 ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
4177 if (mdl->contiguous)
4179 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4180 if (mdl->exact == gcvTRUE)
4182 free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
4187 __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
4192 _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
4195 /* Remove the node from global list. */
4196 if (mdl == Os->mdlHead)
4198 if ((Os->mdlHead = mdl->next) == gcvNULL)
4200 Os->mdlTail = gcvNULL;
4205 mdl->prev->next = mdl->next;
4207 if (mdl == Os->mdlTail)
4209 Os->mdlTail = mdl->prev;
4213 mdl->next->prev = mdl->prev;
4219 /* Free the structure... */
4220 gcmkVERIFY_OK(_DestroyMdl(mdl));
4224 return gcvSTATUS_OK;
4227 /*******************************************************************************
4231 ** Lock memory allocated from the paged pool.
4236 ** Pointer to an gckOS object.
4238 ** gctPHYS_ADDR Physical
4239 ** Physical address of the allocation.
4242 ** Number of bytes of the allocation.
4244 ** gctBOOL Cacheable
4245 ** Cache mode of mapping.
4249 ** gctPOINTER * Logical
4250 ** Pointer to a variable that receives the address of the mapped
4253 ** gctSIZE_T * PageCount
4254 ** Pointer to a variable that receives the number of pages required for
4255 ** the page table according to the GPU page size.
4260 IN gctPHYS_ADDR Physical,
4262 IN gctBOOL Cacheable,
4263 OUT gctPOINTER * Logical,
4264 OUT gctSIZE_T * PageCount
4268 PLINUX_MDL_MAP mdlMap;
4270 unsigned long start;
4274 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
4276 /* Verify the arguments. */
4277 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4278 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4279 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4280 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
4282 mdl = (PLINUX_MDL) Physical;
4286 mdlMap = FindMdlMap(mdl, _GetProcessID());
4288 if (mdlMap == gcvNULL)
4290 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
4292 if (mdlMap == gcvNULL)
4296 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4297 return gcvSTATUS_OUT_OF_MEMORY;
4301 if (mdlMap->vmaAddr == gcvNULL)
4303 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
4304 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
4306 mdl->numPages * PAGE_SIZE,
4307 PROT_READ | PROT_WRITE,
4311 down_write(¤t->mm->mmap_sem);
4313 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
4315 mdl->numPages * PAGE_SIZE,
4316 PROT_READ | PROT_WRITE,
4320 up_write(¤t->mm->mmap_sem);
4324 gcvLEVEL_INFO, gcvZONE_OS,
4325 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
4326 __FUNCTION__, __LINE__,
4327 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
4328 (gctUINT32)(gctUINTPTR_T)mdl
4331 if (IS_ERR(mdlMap->vmaAddr))
4334 gcvLEVEL_INFO, gcvZONE_OS,
4335 "%s(%d): do_mmap_pgoff error",
4336 __FUNCTION__, __LINE__
4339 mdlMap->vmaAddr = gcvNULL;
4343 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4344 return gcvSTATUS_OUT_OF_MEMORY;
4347 down_write(¤t->mm->mmap_sem);
4349 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
4351 if (mdlMap->vma == gcvNULL)
4353 up_write(¤t->mm->mmap_sem);
4356 gcvLEVEL_INFO, gcvZONE_OS,
4357 "%s(%d): find_vma error",
4358 __FUNCTION__, __LINE__
4361 mdlMap->vmaAddr = gcvNULL;
4365 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
4366 return gcvSTATUS_OUT_OF_RESOURCES;
4369 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
4371 if (Cacheable == gcvFALSE)
4373 /* Make this mapping non-cached. */
4374 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
4379 /* Now map all the vmalloc pages to this user address. */
4380 if (mdl->contiguous)
4382 /* map kernel memory to user space.. */
4383 if (remap_pfn_range(mdlMap->vma,
4384 mdlMap->vma->vm_start,
4385 page_to_pfn(mdl->u.contiguousPages),
4386 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
4387 mdlMap->vma->vm_page_prot) < 0)
4389 up_write(¤t->mm->mmap_sem);
4392 gcvLEVEL_INFO, gcvZONE_OS,
4393 "%s(%d): unable to mmap ret",
4394 __FUNCTION__, __LINE__
4397 mdlMap->vmaAddr = gcvNULL;
4401 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4402 return gcvSTATUS_OUT_OF_MEMORY;
4407 start = mdlMap->vma->vm_start;
4409 for (i = 0; i < mdl->numPages; i++)
4411 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
4413 if (remap_pfn_range(mdlMap->vma,
4417 mdlMap->vma->vm_page_prot) < 0)
4419 up_write(¤t->mm->mmap_sem);
4422 gcvLEVEL_INFO, gcvZONE_OS,
4423 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
4424 __FUNCTION__, __LINE__,
4425 (gctUINT32)(gctUINTPTR_T)Physical,
4426 (gctUINT32)(gctUINTPTR_T)*Logical,
4427 (gctUINT32)(gctUINTPTR_T)addr,
4428 (gctUINT32)(gctUINTPTR_T)start
4431 mdlMap->vmaAddr = gcvNULL;
4435 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4436 return gcvSTATUS_OUT_OF_MEMORY;
4444 up_write(¤t->mm->mmap_sem);
4449 /* Convert pointer to MDL. */
4450 *Logical = mdlMap->vmaAddr;
4452 /* Return the page number according to the GPU page size. */
4453 gcmkASSERT((PAGE_SIZE % 4096) == 0);
4454 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
4456 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
4460 gcmkVERIFY_OK(gckOS_CacheFlush(
4465 (gctPOINTER)mdlMap->vmaAddr,
4466 mdl->numPages * PAGE_SIZE
4470 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
4471 return gcvSTATUS_OK;
4474 /*******************************************************************************
4478 ** Map paged memory into a page table.
4483 ** Pointer to an gckOS object.
4485 ** gctPHYS_ADDR Physical
4486 ** Physical address of the allocation.
4488 ** gctSIZE_T PageCount
4489 ** Number of pages required for the physical address.
4491 ** gctPOINTER PageTable
4492 ** Pointer to the page table to fill in.
4501 IN gctPHYS_ADDR Physical,
4502 IN gctSIZE_T PageCount,
4503 IN gctPOINTER PageTable
4506 return gckOS_MapPagesEx(Os,
4517 IN gctPHYS_ADDR Physical,
4518 IN gctSIZE_T PageCount,
4519 IN gctPOINTER PageTable
4522 gceSTATUS status = gcvSTATUS_OK;
4526 #if gcdNONPAGED_MEMORY_CACHEABLE
4530 gctPHYS_ADDR pageTablePhysical;
4533 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
4534 Os, Core, Physical, PageCount, PageTable);
4536 /* Verify the arguments. */
4537 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4538 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4539 gcmkVERIFY_ARGUMENT(PageCount > 0);
4540 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
4542 /* Convert pointer to MDL. */
4543 mdl = (PLINUX_MDL)Physical;
4546 gcvLEVEL_INFO, gcvZONE_OS,
4547 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4548 __FUNCTION__, __LINE__,
4549 (gctUINT32)(gctUINTPTR_T)Physical,
4550 (gctUINT32)(gctUINTPTR_T)PageCount,
4556 table = (gctUINT32 *)PageTable;
4557 #if gcdNONPAGED_MEMORY_CACHEABLE
4558 mmu = Os->device->kernels[Core]->mmu;
4559 bytes = PageCount * sizeof(*table);
4560 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4563 /* Get all the physical addresses and store them in the page table. */
4569 /* Try to get the user pages so DMA can happen. */
4570 while (PageCount-- > 0)
4573 if (Core == gcvCORE_VG)
4575 if (mdl->contiguous)
4578 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4579 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4585 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4586 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4593 if (mdl->contiguous)
4596 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4597 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4603 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4604 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4616 gcvLEVEL_INFO, gcvZONE_OS,
4617 "%s(%d): we should not get this call for Non Paged Memory!",
4618 __FUNCTION__, __LINE__
4621 while (PageCount-- > 0)
4624 if (Core == gcvCORE_VG)
4627 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4628 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4635 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4636 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4644 #if gcdNONPAGED_MEMORY_CACHEABLE
4645 /* Get physical address of pageTable */
4646 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4647 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4649 /* Flush the mmu page table cache. */
4650 gcmkONERROR(gckOS_CacheClean(
4664 /* Return the status. */
4669 /*******************************************************************************
4671 ** gckOS_UnlockPages
4673 ** Unlock memory allocated from the paged pool.
4678 ** Pointer to an gckOS object.
4680 ** gctPHYS_ADDR Physical
4681 ** Physical address of the allocation.
4684 ** Number of bytes of the allocation.
4686 ** gctPOINTER Logical
4687 ** Address of the mapped memory.
4696 IN gctPHYS_ADDR Physical,
4698 IN gctPOINTER Logical
4701 PLINUX_MDL_MAP mdlMap;
4702 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4704 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4705 Os, Physical, Bytes, Logical);
4707 /* Verify the arguments. */
4708 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4709 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4710 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4712 /* Make sure there is already a mapping...*/
4713 gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
4714 || mdl->u.contiguousPages != gcvNULL);
4720 while (mdlMap != gcvNULL)
4722 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4724 if (--mdlMap->count == 0)
4726 _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
4727 mdlMap->vmaAddr = gcvNULL;
4731 mdlMap = mdlMap->next;
4738 return gcvSTATUS_OK;
4742 /*******************************************************************************
4744 ** gckOS_AllocateContiguous
4746 ** Allocate memory from the contiguous pool.
4751 ** Pointer to an gckOS object.
4753 ** gctBOOL InUserSpace
4754 ** gcvTRUE if the pages need to be mapped into user space.
4756 ** gctSIZE_T * Bytes
4757 ** Pointer to the number of bytes to allocate.
4761 ** gctSIZE_T * Bytes
4762 ** Pointer to a variable that receives the number of bytes allocated.
4764 ** gctPHYS_ADDR * Physical
4765 ** Pointer to a variable that receives the physical address of the
4766 ** memory allocation.
4768 ** gctPOINTER * Logical
4769 ** Pointer to a variable that receives the logical address of the
4770 ** memory allocation.
4773 gckOS_AllocateContiguous(
4775 IN gctBOOL InUserSpace,
4776 IN OUT gctSIZE_T * Bytes,
4777 OUT gctPHYS_ADDR * Physical,
4778 OUT gctPOINTER * Logical
4783 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4784 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4786 /* Verify the arguments. */
4787 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4788 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4789 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4790 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4791 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4793 /* Same as non-paged memory for now. */
4794 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4801 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4802 *Bytes, *Physical, *Logical);
4803 return gcvSTATUS_OK;
4806 /* Return the status. */
4811 /*******************************************************************************
4813 ** gckOS_FreeContiguous
4815 ** Free memory allocated from the contiguous pool.
4820 ** Pointer to an gckOS object.
4822 ** gctPHYS_ADDR Physical
4823 ** Physical address of the allocation.
4825 ** gctPOINTER Logical
4826 ** Logicval address of the allocation.
4829 ** Number of bytes of the allocation.
4836 gckOS_FreeContiguous(
4838 IN gctPHYS_ADDR Physical,
4839 IN gctPOINTER Logical,
4845 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4846 Os, Physical, Logical, Bytes);
4848 /* Verify the arguments. */
4849 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4850 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4851 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4852 gcmkVERIFY_ARGUMENT(Bytes > 0);
4854 /* Same of non-paged memory for now. */
4855 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4859 return gcvSTATUS_OK;
4862 /* Return the status. */
4868 /******************************************************************************
4870 ** gckOS_GetKernelLogical
4872 ** Return the kernel logical pointer that corresponods to the specified
4873 ** hardware address.
4878 ** Pointer to an gckOS object.
4880 ** gctUINT32 Address
4881 ** Hardware physical address.
4885 ** gctPOINTER * KernelPointer
4886 ** Pointer to a variable receiving the pointer in kernel address space.
4889 gckOS_GetKernelLogical(
4891 IN gctUINT32 Address,
4892 OUT gctPOINTER * KernelPointer
4895 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4899 gckOS_GetKernelLogicalEx(
4902 IN gctUINT32 Address,
4903 OUT gctPOINTER * KernelPointer
4908 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4912 gckGALDEVICE device;
4918 /* Extract the pointer to the gckGALDEVICE class. */
4919 device = (gckGALDEVICE) Os->device;
4921 /* Kernel shortcut. */
4922 kernel = device->kernels[Core];
4924 if (Core == gcvCORE_VG)
4926 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4927 kernel->vg->hardware, Address, &pool, &offset
4933 /* Split the memory address into a pool type and offset. */
4934 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4935 kernel->hardware, Address, &pool, &offset
4939 /* Dispatch on pool. */
4942 case gcvPOOL_LOCAL_INTERNAL:
4943 /* Internal memory. */
4944 logical = device->internalLogical;
4947 case gcvPOOL_LOCAL_EXTERNAL:
4948 /* External memory. */
4949 logical = device->externalLogical;
4952 case gcvPOOL_SYSTEM:
4953 /* System memory. */
4954 logical = device->contiguousBase;
4958 /* Invalid memory pool. */
4960 return gcvSTATUS_INVALID_ARGUMENT;
4963 /* Build logical address of specified address. */
4964 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4967 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4968 return gcvSTATUS_OK;
4972 /* Return status. */
4978 /*******************************************************************************
4980 ** gckOS_MapUserPointer
4982 ** Map a pointer from the user process into the kernel address space.
4987 ** Pointer to an gckOS object.
4989 ** gctPOINTER Pointer
4990 ** Pointer in user process space that needs to be mapped.
4993 ** Number of bytes that need to be mapped.
4997 ** gctPOINTER * KernelPointer
4998 ** Pointer to a variable receiving the mapped pointer in kernel address
5002 gckOS_MapUserPointer(
5004 IN gctPOINTER Pointer,
5006 OUT gctPOINTER * KernelPointer
5009 gctPOINTER buf = gcvNULL;
5012 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
5014 /* Verify the arguments. */
5015 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5016 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5017 gcmkVERIFY_ARGUMENT(Size > 0);
5018 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5020 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
5025 "%s(%d): Failed to allocate memory.",
5026 __FUNCTION__, __LINE__
5029 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
5030 return gcvSTATUS_OUT_OF_MEMORY;
5033 len = copy_from_user(buf, Pointer, Size);
5038 "%s(%d): Failed to copy data from user.",
5039 __FUNCTION__, __LINE__
5047 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
5048 return gcvSTATUS_GENERIC_IO;
5051 *KernelPointer = buf;
5053 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
5054 return gcvSTATUS_OK;
5057 /*******************************************************************************
5059 ** gckOS_UnmapUserPointer
5061 ** Unmap a user process pointer from the kernel address space.
5066 ** Pointer to an gckOS object.
5068 ** gctPOINTER Pointer
5069 ** Pointer in user process space that needs to be unmapped.
5072 ** Number of bytes that need to be unmapped.
5074 ** gctPOINTER KernelPointer
5075 ** Pointer in kernel address space that needs to be unmapped.
5082 gckOS_UnmapUserPointer(
5084 IN gctPOINTER Pointer,
5086 IN gctPOINTER KernelPointer
5091 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
5092 Os, Pointer, Size, KernelPointer);
5095 /* Verify the arguments. */
5096 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5097 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5098 gcmkVERIFY_ARGUMENT(Size > 0);
5099 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5101 len = copy_to_user(Pointer, KernelPointer, Size);
5103 kfree(KernelPointer);
5109 "%s(%d): Failed to copy data to user.",
5110 __FUNCTION__, __LINE__
5113 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
5114 return gcvSTATUS_GENERIC_IO;
5118 return gcvSTATUS_OK;
5121 /*******************************************************************************
5123 ** gckOS_QueryNeedCopy
5125 ** Query whether the memory can be accessed or mapped directly or it has to be
5131 ** Pointer to an gckOS object.
5133 ** gctUINT32 ProcessID
5134 ** Process ID of the current process.
5138 ** gctBOOL_PTR NeedCopy
5139 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
5140 ** gcvFALSE if the memory can be accessed or mapped dircetly.
5143 gckOS_QueryNeedCopy(
5145 IN gctUINT32 ProcessID,
5146 OUT gctBOOL_PTR NeedCopy
5149 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
5151 /* Verify the arguments. */
5152 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5153 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
5155 /* We need to copy data. */
5156 *NeedCopy = gcvTRUE;
5159 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
5160 return gcvSTATUS_OK;
5163 /*******************************************************************************
5165 ** gckOS_CopyFromUserData
5167 ** Copy data from user to kernel memory.
5172 ** Pointer to an gckOS object.
5174 ** gctPOINTER KernelPointer
5175 ** Pointer to kernel memory.
5177 ** gctPOINTER Pointer
5178 ** Pointer to user memory.
5181 ** Number of bytes to copy.
5188 gckOS_CopyFromUserData(
5190 IN gctPOINTER KernelPointer,
5191 IN gctPOINTER Pointer,
5197 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5198 Os, KernelPointer, Pointer, Size);
5200 /* Verify the arguments. */
5201 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5202 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5203 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5204 gcmkVERIFY_ARGUMENT(Size > 0);
5206 /* Copy data from user. */
5207 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
5209 /* Could not copy all the bytes. */
5210 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5215 return gcvSTATUS_OK;
5218 /* Return the status. */
5223 /*******************************************************************************
5225 ** gckOS_CopyToUserData
5227 ** Copy data from kernel to user memory.
5232 ** Pointer to an gckOS object.
5234 ** gctPOINTER KernelPointer
5235 ** Pointer to kernel memory.
5237 ** gctPOINTER Pointer
5238 ** Pointer to user memory.
5241 ** Number of bytes to copy.
5248 gckOS_CopyToUserData(
5250 IN gctPOINTER KernelPointer,
5251 IN gctPOINTER Pointer,
5257 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5258 Os, KernelPointer, Pointer, Size);
5260 /* Verify the arguments. */
5261 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5262 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5263 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5264 gcmkVERIFY_ARGUMENT(Size > 0);
5266 /* Copy data to user. */
5267 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
5269 /* Could not copy all the bytes. */
5270 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5275 return gcvSTATUS_OK;
5278 /* Return the status. */
5283 /*******************************************************************************
5285 ** gckOS_WriteMemory
5287 ** Write data to a memory.
5292 ** Pointer to an gckOS object.
5294 ** gctPOINTER Address
5295 ** Address of the memory to write to.
5298 ** Data for register.
5307 IN gctPOINTER Address,
5312 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
5314 /* Verify the arguments. */
5315 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5318 if (access_ok(VERIFY_WRITE, Address, 4))
5321 if(put_user(Data, (gctUINT32*)Address))
5323 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
5328 /* Kernel address. */
5329 *(gctUINT32 *)Address = Data;
5334 return gcvSTATUS_OK;
5341 /*******************************************************************************
5343 ** gckOS_MapUserMemory
5345 ** Lock down a user buffer and return an DMA'able address to be used by the
5346 ** hardware to access it.
5350 ** gctPOINTER Memory
5351 ** Pointer to memory to lock down.
5354 ** Size in bytes of the memory to lock down.
5358 ** gctPOINTER * Info
5359 ** Pointer to variable receiving the information record required by
5360 ** gckOS_UnmapUserMemory.
5362 ** gctUINT32_PTR Address
5363 ** Pointer to a variable that will receive the address DMA'able by the
5367 gckOS_MapUserMemory(
5370 IN gctPOINTER Memory,
5371 IN gctUINT32 Physical,
5373 OUT gctPOINTER * Info,
5374 OUT gctUINT32_PTR Address
5379 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
5382 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
5385 return gcvSTATUS_OK;
5392 gctSIZE_T pageCount, i, j;
5393 gctUINT32_PTR pageTable;
5394 gctUINT32 address = 0, physical = ~0U;
5395 gctUINTPTR_T start, end, memory;
5399 gcsPageInfo_PTR info = gcvNULL;
5400 struct page **pages = gcvNULL;
5402 /* Verify the arguments. */
5403 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5404 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
5405 gcmkVERIFY_ARGUMENT(Size > 0);
5406 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5407 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5411 memory = (gctUINTPTR_T) Memory;
5413 /* Get the number of required pages. */
5414 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5415 start = memory >> PAGE_SHIFT;
5416 pageCount = end - start;
5419 gcvLEVEL_INFO, gcvZONE_OS,
5420 "%s(%d): pageCount: %d.",
5421 __FUNCTION__, __LINE__,
5426 if ((memory + Size) < memory)
5428 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5429 return gcvSTATUS_INVALID_ARGUMENT;
5432 MEMORY_MAP_LOCK(Os);
5434 /* Allocate the Info struct. */
5435 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
5437 if (info == gcvNULL)
5439 status = gcvSTATUS_OUT_OF_MEMORY;
5443 /* Allocate the array of page addresses. */
5444 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
5446 if (pages == gcvNULL)
5448 status = gcvSTATUS_OUT_OF_MEMORY;
5452 if (Physical != ~0U)
5454 for (i = 0; i < pageCount; i++)
5456 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
5462 /* Get the user pages. */
5463 down_read(¤t->mm->mmap_sem);
5465 result = get_user_pages(current,
5475 up_read(¤t->mm->mmap_sem);
5477 if (result <=0 || result < pageCount)
5479 struct vm_area_struct *vma;
5481 /* Release the pages if any. */
5484 for (i = 0; i < result; i++)
5486 if (pages[i] == gcvNULL)
5491 page_cache_release(pages[i]);
5498 vma = find_vma(current->mm, memory);
5500 if (vma && (vma->vm_flags & VM_PFNMAP))
5504 gctUINTPTR_T logical = memory;
5506 for (i = 0; i < pageCount; i++)
5508 pgd_t * pgd = pgd_offset(current->mm, logical);
5509 pud_t * pud = pud_offset(pgd, logical);
5513 pmd_t * pmd = pmd_offset(pud, logical);
5514 pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
5517 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5522 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5525 pages[i] = pte_page(*pte);
5526 pte_unmap_unlock(pte, ptl);
5528 /* Advance to next. */
5529 logical += PAGE_SIZE;
5534 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5537 /* Check if this memory is contiguous for old mmu. */
5538 if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
5540 for (i = 1; i < pageCount; i++)
5542 if (pages[i] != nth_page(pages[0], i))
5544 /* Non-contiguous. */
5551 /* Contiguous memory. */
5552 physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
5554 if (!((physical - Os->device->baseAddress) & 0x80000000))
5559 info->pages = gcvNULL;
5560 info->pageTable = gcvNULL;
5562 MEMORY_MAP_UNLOCK(Os);
5564 *Address = physical - Os->device->baseAddress;
5567 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5570 return gcvSTATUS_OK;
5575 /* Reference pages. */
5576 for (i = 0; i < pageCount; i++)
5583 for (i = 0; i < pageCount; i++)
5587 get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
5590 /* Flush(clean) the data cache. */
5591 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5592 (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
5593 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5598 if (Core == gcvCORE_VG)
5600 /* Allocate pages inside the page table. */
5601 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5602 pageCount * (PAGE_SIZE/4096),
5603 (gctPOINTER *) &pageTable,
5609 /* Allocate pages inside the page table. */
5610 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5611 pageCount * (PAGE_SIZE/4096),
5612 (gctPOINTER *) &pageTable,
5616 /* Fill the page table. */
5617 for (i = 0; i < pageCount; i++)
5620 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5622 phys = page_to_phys(pages[i]);
5625 if (Core == gcvCORE_VG)
5627 /* Get the physical address from page struct. */
5629 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5636 /* Get the physical address from page struct. */
5638 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5643 for (j = 1; j < (PAGE_SIZE/4096); j++)
5645 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5649 gcvLEVEL_INFO, gcvZONE_OS,
5650 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5651 __FUNCTION__, __LINE__,
5652 i, phys, pageTable[i]);
5656 if (Core == gcvCORE_VG)
5658 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5663 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
5666 /* Save pointer to page table. */
5667 info->pageTable = pageTable;
5668 info->pages = pages;
5670 *Info = (gctPOINTER) info;
5673 gcvLEVEL_INFO, gcvZONE_OS,
5674 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5675 __FUNCTION__, __LINE__,
5681 offset = (Physical != ~0U)
5682 ? (Physical & ~PAGE_MASK)
5683 : (memory & ~PAGE_MASK);
5685 /* Return address. */
5686 *Address = address + offset;
5689 gcvLEVEL_INFO, gcvZONE_OS,
5690 "%s(%d): Address: 0x%X.",
5691 __FUNCTION__, __LINE__,
5696 status = gcvSTATUS_OK;
5702 if (gcmIS_ERROR(status))
5706 "%s(%d): error occured: %d.",
5707 __FUNCTION__, __LINE__,
5711 /* Release page array. */
5712 if (result > 0 && pages != gcvNULL)
5716 "%s(%d): error: page table is freed.",
5717 __FUNCTION__, __LINE__
5720 for (i = 0; i < result; i++)
5722 if (pages[i] == gcvNULL)
5726 page_cache_release(pages[i]);
5730 if (info!= gcvNULL && pages != gcvNULL)
5734 "%s(%d): error: pages is freed.",
5735 __FUNCTION__, __LINE__
5738 /* Free the page table. */
5740 info->pages = gcvNULL;
5743 /* Release page info struct. */
5744 if (info != gcvNULL)
5748 "%s(%d): error: info is freed.",
5749 __FUNCTION__, __LINE__
5752 /* Free the page info struct. */
5758 MEMORY_MAP_UNLOCK(Os);
5760 /* Return the status. */
5761 if (gcmIS_SUCCESS(status))
5763 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5775 /*******************************************************************************
5777 ** gckOS_UnmapUserMemory
5779 ** Unlock a user buffer and that was previously locked down by
5780 ** gckOS_MapUserMemory.
5784 ** gctPOINTER Memory
5785 ** Pointer to memory to unlock.
5788 ** Size in bytes of the memory to unlock.
5791 ** Information record returned by gckOS_MapUserMemory.
5793 ** gctUINT32_PTR Address
5794 ** The address returned by gckOS_MapUserMemory.
5801 gckOS_UnmapUserMemory(
5804 IN gctPOINTER Memory,
5807 IN gctUINT32 Address
5812 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5813 Os, Core, Memory, Size, Info, Address);
5816 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5819 return gcvSTATUS_OK;
5826 gctUINTPTR_T memory, start, end;
5827 gcsPageInfo_PTR info;
5828 gctSIZE_T pageCount, i;
5829 struct page **pages;
5831 /* Verify the arguments. */
5832 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5833 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5834 gcmkVERIFY_ARGUMENT(Size > 0);
5835 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5839 info = (gcsPageInfo_PTR) Info;
5841 pages = info->pages;
5844 gcvLEVEL_INFO, gcvZONE_OS,
5845 "%s(%d): info=0x%X, pages=0x%X.",
5846 __FUNCTION__, __LINE__,
5850 /* Invalid page array. */
5851 if (pages == gcvNULL && info->pageTable == gcvNULL)
5856 return gcvSTATUS_OK;
5859 memory = (gctUINTPTR_T)Memory;
5860 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5861 start = memory >> PAGE_SHIFT;
5862 pageCount = end - start;
5865 if ((memory + Size) < memory)
5867 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5868 return gcvSTATUS_INVALID_ARGUMENT;
5872 gcvLEVEL_INFO, gcvZONE_OS,
5873 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5874 __FUNCTION__, __LINE__,
5875 memory, pageCount, info->pageTable
5878 MEMORY_MAP_LOCK(Os);
5880 gcmkASSERT(info->pageTable != gcvNULL);
5883 if (Core == gcvCORE_VG)
5885 /* Free the pages from the MMU. */
5886 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5888 pageCount * (PAGE_SIZE/4096)
5894 /* Free the pages from the MMU. */
5895 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5897 pageCount * (PAGE_SIZE/4096)
5901 /* Release the page cache. */
5904 for (i = 0; i < pageCount; i++)
5907 gcvLEVEL_INFO, gcvZONE_OS,
5908 "%s(%d): pages[%d]: 0x%X.",
5909 __FUNCTION__, __LINE__,
5913 if (!PageReserved(pages[i]))
5915 SetPageDirty(pages[i]);
5918 page_cache_release(pages[i]);
5923 status = gcvSTATUS_OK;
5927 if (info != gcvNULL)
5929 /* Free the page array. */
5930 if (info->pages != gcvNULL)
5938 MEMORY_MAP_UNLOCK(Os);
5940 /* Return the status. */
5947 /*******************************************************************************
5949 ** gckOS_GetBaseAddress
5951 ** Get the base address for the physical memory.
5956 ** Pointer to the gckOS object.
5960 ** gctUINT32_PTR BaseAddress
5961 ** Pointer to a variable that will receive the base address.
5964 gckOS_GetBaseAddress(
5966 OUT gctUINT32_PTR BaseAddress
5969 gcmkHEADER_ARG("Os=0x%X", Os);
5971 /* Verify the arguments. */
5972 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5973 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5975 /* Return base address. */
5976 *BaseAddress = Os->device->baseAddress;
5979 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5980 return gcvSTATUS_OK;
5984 gckOS_SuspendInterrupt(
5988 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5992 gckOS_SuspendInterruptEx(
5997 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5999 /* Verify the arguments. */
6000 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6002 disable_irq(Os->device->irqLines[Core]);
6005 return gcvSTATUS_OK;
6009 gckOS_ResumeInterrupt(
6013 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
6017 gckOS_ResumeInterruptEx(
6022 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
6024 /* Verify the arguments. */
6025 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6027 enable_irq(Os->device->irqLines[Core]);
6030 return gcvSTATUS_OK;
6035 IN gctPOINTER Destination,
6036 IN gctCONST_POINTER Source,
6040 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
6041 Destination, Source, Bytes);
6043 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
6044 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
6045 gcmkVERIFY_ARGUMENT(Bytes > 0);
6047 memcpy(Destination, Source, Bytes);
6050 return gcvSTATUS_OK;
6055 IN gctPOINTER Memory,
6059 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
6061 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
6062 gcmkVERIFY_ARGUMENT(Bytes > 0);
6064 memset(Memory, 0, Bytes);
6067 return gcvSTATUS_OK;
6070 /*******************************************************************************
6071 ********************************* Cache Control ********************************
6072 *******************************************************************************/
6074 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
6075 static inline gceSTATUS
6077 gceCACHEOPERATION Type,
6078 unsigned long Start,
6084 case gcvCACHE_CLEAN:
6085 outer_clean_range(Start, End);
6087 case gcvCACHE_INVALIDATE:
6088 outer_inv_range(Start, End);
6090 case gcvCACHE_FLUSH:
6091 outer_flush_range(Start, End);
6094 return gcvSTATUS_INVALID_ARGUMENT;
6097 return gcvSTATUS_OK;
6100 #if gcdENABLE_OUTER_CACHE_PATCH
6101 /*******************************************************************************
6102 ** _HandleOuterCache
6104 ** Handle the outer cache for the specified addresses.
6109 ** Pointer to gckOS object.
6111 ** gctUINT32 ProcessID
6112 ** Process ID Logical belongs.
6114 ** gctPHYS_ADDR Handle
6115 ** Physical address handle. If gcvNULL it is video memory.
6117 ** gctPOINTER Physical
6118 ** Physical address to flush.
6120 ** gctPOINTER Logical
6121 ** Logical address to flush.
6124 ** Size of the address range in bytes to flush.
6126 ** gceOUTERCACHE_OPERATION Type
6127 ** Operation need to be execute.
6132 IN gctUINT32 ProcessID,
6133 IN gctPHYS_ADDR Handle,
6134 IN gctPOINTER Physical,
6135 IN gctPOINTER Logical,
6137 IN gceCACHEOPERATION Type
6141 gctUINT32 i, pageNum;
6142 unsigned long paddr;
6145 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6146 Os, ProcessID, Handle, Logical, Bytes);
6148 if (Physical != gcvNULL)
6150 /* Non paged memory or gcvPOOL_USER surface */
6151 paddr = (unsigned long) Physical;
6152 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6154 else if ((Handle == gcvNULL)
6155 || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
6158 /* Video Memory or contiguous virtual memory */
6159 gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
6160 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6164 /* Non contiguous virtual memory */
6165 vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
6166 pageNum = GetPageCount(Bytes, 0);
6168 for (i = 0; i < pageNum; i += 1)
6170 gcmkONERROR(_ConvertLogical2Physical(
6172 vaddr + PAGE_SIZE * i,
6178 gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
6186 return gcvSTATUS_OK;
6189 /* Return the status. */
6196 /*******************************************************************************
6199 ** Clean the cache for the specified addresses. The GPU is going to need the
6200 ** data. If the system is allocating memory as non-cachable, this function can
6206 ** Pointer to gckOS object.
6208 ** gctUINT32 ProcessID
6209 ** Process ID Logical belongs.
6211 ** gctPHYS_ADDR Handle
6212 ** Physical address handle. If gcvNULL it is video memory.
6214 ** gctPOINTER Physical
6215 ** Physical address to flush.
6217 ** gctPOINTER Logical
6218 ** Logical address to flush.
6221 ** Size of the address range in bytes to flush.
6226 IN gctUINT32 ProcessID,
6227 IN gctPHYS_ADDR Handle,
6228 IN gctPOINTER Physical,
6229 IN gctPOINTER Logical,
6233 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6234 Os, ProcessID, Handle, Logical, Bytes);
6236 /* Verify the arguments. */
6237 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6238 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6239 gcmkVERIFY_ARGUMENT(Bytes > 0);
6241 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6246 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
6248 dmac_clean_range(Logical, Logical + Bytes);
6251 #if defined(CONFIG_OUTER_CACHE)
6253 #if gcdENABLE_OUTER_CACHE_PATCH
6254 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
6256 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6260 #elif defined(CONFIG_MIPS)
6262 dma_cache_wback((unsigned long) Logical, Bytes);
6264 #elif defined(CONFIG_PPC)
6269 dma_sync_single_for_device(
6271 (dma_addr_t)Physical,
6279 return gcvSTATUS_OK;
6282 /*******************************************************************************
6283 ** gckOS_CacheInvalidate
6285 ** Invalidate the cache for the specified addresses. The GPU is going to need
6286 ** data. If the system is allocating memory as non-cachable, this function can
6292 ** Pointer to gckOS object.
6294 ** gctUINT32 ProcessID
6295 ** Process ID Logical belongs.
6297 ** gctPHYS_ADDR Handle
6298 ** Physical address handle. If gcvNULL it is video memory.
6300 ** gctPOINTER Logical
6301 ** Logical address to flush.
6304 ** Size of the address range in bytes to flush.
6307 gckOS_CacheInvalidate(
6309 IN gctUINT32 ProcessID,
6310 IN gctPHYS_ADDR Handle,
6311 IN gctPOINTER Physical,
6312 IN gctPOINTER Logical,
6316 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6317 Os, ProcessID, Handle, Logical, Bytes);
6319 /* Verify the arguments. */
6320 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6321 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6322 gcmkVERIFY_ARGUMENT(Bytes > 0);
6324 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6328 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6329 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
6331 dmac_inv_range(Logical, Logical + Bytes);
6334 #if defined(CONFIG_OUTER_CACHE)
6336 #if gcdENABLE_OUTER_CACHE_PATCH
6337 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
6339 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6343 #elif defined(CONFIG_MIPS)
6344 dma_cache_inv((unsigned long) Logical, Bytes);
6345 #elif defined(CONFIG_PPC)
6348 dma_sync_single_for_device(
6350 (dma_addr_t)Physical,
6358 return gcvSTATUS_OK;
6361 /*******************************************************************************
6364 ** Clean the cache for the specified addresses and invalidate the lines as
6365 ** well. The GPU is going to need and modify the data. If the system is
6366 ** allocating memory as non-cachable, this function can be ignored.
6371 ** Pointer to gckOS object.
6373 ** gctUINT32 ProcessID
6374 ** Process ID Logical belongs.
6376 ** gctPHYS_ADDR Handle
6377 ** Physical address handle. If gcvNULL it is video memory.
6379 ** gctPOINTER Logical
6380 ** Logical address to flush.
6383 ** Size of the address range in bytes to flush.
6388 IN gctUINT32 ProcessID,
6389 IN gctPHYS_ADDR Handle,
6390 IN gctPOINTER Physical,
6391 IN gctPOINTER Logical,
6395 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6396 Os, ProcessID, Handle, Logical, Bytes);
6398 /* Verify the arguments. */
6399 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6400 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6401 gcmkVERIFY_ARGUMENT(Bytes > 0);
6403 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6406 dmac_flush_range(Logical, Logical + Bytes);
6408 #if defined(CONFIG_OUTER_CACHE)
6410 #if gcdENABLE_OUTER_CACHE_PATCH
6411 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6413 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6417 #elif defined(CONFIG_MIPS)
6418 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6419 #elif defined(CONFIG_PPC)
6422 dma_sync_single_for_device(
6424 (dma_addr_t)Physical,
6432 return gcvSTATUS_OK;
6435 /*******************************************************************************
6436 ********************************* Broadcasting *********************************
6437 *******************************************************************************/
6439 /*******************************************************************************
6443 ** System hook for broadcast events from the kernel driver.
6448 ** Pointer to the gckOS object.
6450 ** gckHARDWARE Hardware
6451 ** Pointer to the gckHARDWARE object.
6453 ** gceBROADCAST Reason
6454 ** Reason for the broadcast. Can be one of the following values:
6456 ** gcvBROADCAST_GPU_IDLE
6457 ** Broadcasted when the kernel driver thinks the GPU might be
6458 ** idle. This can be used to handle power management.
6460 ** gcvBROADCAST_GPU_COMMIT
6461 ** Broadcasted when any client process commits a command
6462 ** buffer. This can be used to handle power management.
6464 ** gcvBROADCAST_GPU_STUCK
6465 ** Broadcasted when the kernel driver hits the timeout waiting
6468 ** gcvBROADCAST_FIRST_PROCESS
6469 ** First process is trying to connect to the kernel.
6471 ** gcvBROADCAST_LAST_PROCESS
6472 ** Last process has detached from the kernel.
6481 IN gckHARDWARE Hardware,
6482 IN gceBROADCAST Reason
6487 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6489 /* Verify the arguments. */
6490 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6491 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6495 case gcvBROADCAST_FIRST_PROCESS:
6496 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6499 case gcvBROADCAST_LAST_PROCESS:
6500 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6504 gckHARDWARE_SetPowerManagementState(Hardware,
6505 gcvPOWER_OFF_BROADCAST));
6508 case gcvBROADCAST_GPU_IDLE:
6509 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6513 gckHARDWARE_SetPowerManagementState(Hardware,
6514 #if gcdPOWER_SUSNPEND_WHEN_IDLE
6515 gcvPOWER_SUSPEND_BROADCAST));
6517 gcvPOWER_IDLE_BROADCAST));
6520 /* Add idle process DB. */
6521 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6524 gcvNULL, gcvNULL, 0));
6527 case gcvBROADCAST_GPU_COMMIT:
6528 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6530 /* Add busy process DB. */
6531 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6534 gcvNULL, gcvNULL, 0));
6538 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6541 case gcvBROADCAST_GPU_STUCK:
6542 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6543 #if !gcdENABLE_RECOVERY
6544 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6546 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6549 case gcvBROADCAST_AXI_BUS_ERROR:
6550 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6551 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6552 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6558 return gcvSTATUS_OK;
6561 /* Return the status. */
6566 /*******************************************************************************
6568 ** gckOS_BroadcastHurry
6570 ** The GPU is running too slow.
6575 ** Pointer to the gckOS object.
6577 ** gckHARDWARE Hardware
6578 ** Pointer to the gckHARDWARE object.
6581 ** The higher the number, the higher the urgency to speed up the GPU.
6582 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6589 gckOS_BroadcastHurry(
6591 IN gckHARDWARE Hardware,
6595 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6597 /* Do whatever you need to do to speed up the GPU now. */
6601 return gcvSTATUS_OK;
6604 /*******************************************************************************
6606 ** gckOS_BroadcastCalibrateSpeed
6608 ** Calibrate the speed of the GPU.
6613 ** Pointer to the gckOS object.
6615 ** gckHARDWARE Hardware
6616 ** Pointer to the gckHARDWARE object.
6618 ** gctUINT Idle, Time
6619 ** Idle/Time will give the percentage the GPU is idle, so you can use
6620 ** this to calibrate the working point of the GPU.
6627 gckOS_BroadcastCalibrateSpeed(
6629 IN gckHARDWARE Hardware,
6634 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6635 Os, Hardware, Idle, Time);
6637 /* Do whatever you need to do to callibrate the GPU speed. */
6641 return gcvSTATUS_OK;
6644 /*******************************************************************************
6645 ********************************** Semaphores **********************************
6646 *******************************************************************************/
6648 /*******************************************************************************
6650 ** gckOS_CreateSemaphore
6652 ** Create a semaphore.
6657 ** Pointer to the gckOS object.
6661 ** gctPOINTER * Semaphore
6662 ** Pointer to the variable that will receive the created semaphore.
6665 gckOS_CreateSemaphore(
6667 OUT gctPOINTER * Semaphore
6671 struct semaphore *sem = gcvNULL;
6673 gcmkHEADER_ARG("Os=0x%X", Os);
6675 /* Verify the arguments. */
6676 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6677 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6679 /* Allocate the semaphore structure. */
6680 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6683 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6686 /* Initialize the semaphore. */
6689 /* Return to caller. */
6690 *Semaphore = (gctPOINTER) sem;
6694 return gcvSTATUS_OK;
6697 /* Return the status. */
6702 /*******************************************************************************
6704 ** gckOS_AcquireSemaphore
6706 ** Acquire a semaphore.
6711 ** Pointer to the gckOS object.
6713 ** gctPOINTER Semaphore
6714 ** Pointer to the semaphore thet needs to be acquired.
6721 gckOS_AcquireSemaphore(
6723 IN gctPOINTER Semaphore
6728 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6730 /* Verify the arguments. */
6731 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6732 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6734 /* Acquire the semaphore. */
6735 if (down_interruptible((struct semaphore *) Semaphore))
6737 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6742 return gcvSTATUS_OK;
6745 /* Return the status. */
6750 /*******************************************************************************
6752 ** gckOS_TryAcquireSemaphore
6754 ** Try to acquire a semaphore.
6759 ** Pointer to the gckOS object.
6761 ** gctPOINTER Semaphore
6762 ** Pointer to the semaphore thet needs to be acquired.
6769 gckOS_TryAcquireSemaphore(
6771 IN gctPOINTER Semaphore
6776 gcmkHEADER_ARG("Os=0x%x", Os);
6778 /* Verify the arguments. */
6779 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6780 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6782 /* Acquire the semaphore. */
6783 if (down_trylock((struct semaphore *) Semaphore))
6786 status = gcvSTATUS_TIMEOUT;
6793 return gcvSTATUS_OK;
6796 /*******************************************************************************
6798 ** gckOS_ReleaseSemaphore
6800 ** Release a previously acquired semaphore.
6805 ** Pointer to the gckOS object.
6807 ** gctPOINTER Semaphore
6808 ** Pointer to the semaphore thet needs to be released.
6815 gckOS_ReleaseSemaphore(
6817 IN gctPOINTER Semaphore
6820 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6822 /* Verify the arguments. */
6823 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6824 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6826 /* Release the semaphore. */
6827 up((struct semaphore *) Semaphore);
6831 return gcvSTATUS_OK;
6834 /*******************************************************************************
6836 ** gckOS_DestroySemaphore
6838 ** Destroy a semaphore.
6843 ** Pointer to the gckOS object.
6845 ** gctPOINTER Semaphore
6846 ** Pointer to the semaphore thet needs to be destroyed.
6853 gckOS_DestroySemaphore(
6855 IN gctPOINTER Semaphore
6858 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6860 /* Verify the arguments. */
6861 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6862 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6864 /* Free the sempahore structure. */
6869 return gcvSTATUS_OK;
6872 /*******************************************************************************
6874 ** gckOS_GetProcessID
6876 ** Get current process ID.
6884 ** gctUINT32_PTR ProcessID
6885 ** Pointer to the variable that receives the process ID.
6889 OUT gctUINT32_PTR ProcessID
6892 /* Get process ID. */
6893 if (ProcessID != gcvNULL)
6895 *ProcessID = _GetProcessID();
6899 return gcvSTATUS_OK;
6902 /*******************************************************************************
6904 ** gckOS_GetThreadID
6906 ** Get current thread ID.
6914 ** gctUINT32_PTR ThreadID
6915 ** Pointer to the variable that receives the thread ID.
6919 OUT gctUINT32_PTR ThreadID
6922 /* Get thread ID. */
6923 if (ThreadID != gcvNULL)
6925 *ThreadID = _GetThreadID();
6929 return gcvSTATUS_OK;
6932 /*******************************************************************************
6934 ** gckOS_SetGPUPower
6936 ** Set the power of the GPU on or off.
6941 ** Pointer to a gckOS object.
6944 ** GPU whose power is set.
6947 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6950 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6964 struct clk *clk_3dcore = Os->device->clk_3d_core;
6965 struct clk *clk_3dshader = Os->device->clk_3d_shader;
6966 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
6967 struct clk *clk_3d_axi = Os->device->clk_3d_axi;
6969 struct clk *clk_2dcore = Os->device->clk_2d_core;
6970 struct clk *clk_2d_axi = Os->device->clk_2d_axi;
6971 struct clk *clk_vg_axi = Os->device->clk_vg_axi;
6972 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6976 gctBOOL oldClockState = gcvFALSE;
6977 gctBOOL oldPowerState = gcvFALSE;
6979 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6981 if (Os->device->kernels[Core] != NULL)
6984 if (Core == gcvCORE_VG)
6986 oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
6987 oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
6992 oldClockState = Os->device->kernels[Core]->hardware->clockState;
6993 oldPowerState = Os->device->kernels[Core]->hardware->powerState;
6998 if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
7000 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7001 if(!IS_ERR(Os->device->gpu_regulator)) {
7002 ret = regulator_enable(Os->device->gpu_regulator);
7004 gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
7005 __FUNCTION__, __LINE__, ret);
7008 imx_gpc_power_up_pu(true);
7012 pm_runtime_get_sync(Os->device->pmdev);
7016 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7017 if (Clock == gcvTRUE) {
7018 if (oldClockState == gcvFALSE) {
7021 clk_enable(clk_3dcore);
7023 clk_enable(clk_3dshader);
7026 clk_enable(clk_2dcore);
7027 clk_enable(clk_2d_axi);
7030 clk_enable(clk_2dcore);
7031 clk_enable(clk_vg_axi);
7038 if (oldClockState == gcvTRUE) {
7042 clk_disable(clk_3dshader);
7043 clk_disable(clk_3dcore);
7046 clk_disable(clk_2dcore);
7047 clk_disable(clk_2d_axi);
7050 clk_disable(clk_2dcore);
7051 clk_disable(clk_vg_axi);
7059 if (Clock == gcvTRUE) {
7060 if (oldClockState == gcvFALSE) {
7063 clk_prepare(clk_3dcore);
7064 clk_enable(clk_3dcore);
7065 clk_prepare(clk_3dshader);
7066 clk_enable(clk_3dshader);
7067 clk_prepare(clk_3d_axi);
7068 clk_enable(clk_3d_axi);
7071 clk_prepare(clk_2dcore);
7072 clk_enable(clk_2dcore);
7073 clk_prepare(clk_2d_axi);
7074 clk_enable(clk_2d_axi);
7077 clk_prepare(clk_2dcore);
7078 clk_enable(clk_2dcore);
7079 clk_prepare(clk_vg_axi);
7080 clk_enable(clk_vg_axi);
7087 if (oldClockState == gcvTRUE) {
7090 clk_disable(clk_3dshader);
7091 clk_unprepare(clk_3dshader);
7092 clk_disable(clk_3dcore);
7093 clk_unprepare(clk_3dcore);
7094 clk_disable(clk_3d_axi);
7095 clk_unprepare(clk_3d_axi);
7098 clk_disable(clk_2dcore);
7099 clk_unprepare(clk_2dcore);
7100 clk_disable(clk_2d_axi);
7101 clk_unprepare(clk_2d_axi);
7104 clk_disable(clk_2dcore);
7105 clk_unprepare(clk_2dcore);
7106 clk_disable(clk_vg_axi);
7107 clk_unprepare(clk_vg_axi);
7115 if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
7118 pm_runtime_put_sync(Os->device->pmdev);
7121 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7122 if(!IS_ERR(Os->device->gpu_regulator))
7123 regulator_disable(Os->device->gpu_regulator);
7125 imx_gpc_power_up_pu(false);
7129 /* TODO: Put your code here. */
7131 return gcvSTATUS_OK;
7134 /*******************************************************************************
7143 ** Pointer to a gckOS object.
7146 ** GPU whose power is set.
7158 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7159 #define SRC_SCR_OFFSET 0
7160 #define BP_SRC_SCR_GPU3D_RST 1
7161 #define BP_SRC_SCR_GPU2D_RST 4
7162 void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
7163 gctUINT32 bit_offset,val;
7165 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
7167 if(Core == gcvCORE_MAJOR) {
7168 bit_offset = BP_SRC_SCR_GPU3D_RST;
7169 } else if((Core == gcvCORE_VG)
7170 ||(Core == gcvCORE_2D)) {
7171 bit_offset = BP_SRC_SCR_GPU2D_RST;
7173 return gcvSTATUS_INVALID_CONFIG;
7175 val = __raw_readl(src_base + SRC_SCR_OFFSET);
7176 val &= ~(1 << (bit_offset));
7177 val |= (1 << (bit_offset));
7178 __raw_writel(val, src_base + SRC_SCR_OFFSET);
7180 while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
7181 (1 << (bit_offset))) != 0) {
7185 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7186 struct reset_control *rstc = Os->device->rstc[Core];
7188 reset_control_reset(rstc);
7190 imx_src_reset_gpu((int)Core);
7192 return gcvSTATUS_OK;
7195 /*******************************************************************************
7197 ** gckOS_PrepareGPUFrequency
7199 ** Prepare to set GPU frequency and voltage.
7204 ** Pointer to a gckOS object.
7207 ** GPU whose frequency and voltage will be set.
7214 gckOS_PrepareGPUFrequency(
7219 return gcvSTATUS_OK;
7222 /*******************************************************************************
7224 ** gckOS_FinishGPUFrequency
7226 ** Finish GPU frequency setting.
7231 ** Pointer to a gckOS object.
7234 ** GPU whose frequency and voltage is set.
7241 gckOS_FinishGPUFrequency(
7246 return gcvSTATUS_OK;
7249 /*******************************************************************************
7251 ** gckOS_QueryGPUFrequency
7253 ** Query the current frequency of the GPU.
7258 ** Pointer to a gckOS object.
7261 ** GPU whose power is set.
7263 ** gctUINT32 * Frequency
7264 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
7267 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
7274 gckOS_QueryGPUFrequency(
7277 OUT gctUINT32 * Frequency,
7278 OUT gctUINT8 * Scale
7281 return gcvSTATUS_OK;
7284 /*******************************************************************************
7286 ** gckOS_SetGPUFrequency
7288 ** Set frequency and voltage of the GPU.
7290 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
7291 ** a real frequency according to this scale and board's configure.
7293 ** 2. BSP should find a suitable voltage for this frequency.
7295 ** 3. BSP must make sure setting take effect before this function returns.
7300 ** Pointer to a gckOS object.
7303 ** GPU whose power is set.
7306 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
7307 ** full frequency and 64 means 64/64 of full frequency.
7314 gckOS_SetGPUFrequency(
7320 return gcvSTATUS_OK;
7323 /*----------------------------------------------------------------------------*/
7324 /*----- Profile --------------------------------------------------------------*/
7327 gckOS_GetProfileTick(
7328 OUT gctUINT64_PTR Tick
7331 struct timespec time;
7333 ktime_get_ts(&time);
7335 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
7337 return gcvSTATUS_OK;
7341 gckOS_QueryProfileTickRate(
7342 OUT gctUINT64_PTR TickRate
7345 struct timespec res;
7347 hrtimer_get_res(CLOCK_MONOTONIC, &res);
7349 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
7351 return gcvSTATUS_OK;
7359 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
7360 return div_u64(Ticks, 1000000);
7362 gctUINT64 rem = Ticks;
7363 gctUINT64 b = 1000000;
7364 gctUINT64 res, d = 1;
7365 gctUINT32 high = rem >> 32;
7367 /* Reduce the thing a bit first */
7369 if (high >= 1000000)
7372 res = (gctUINT64) high << 32;
7373 rem -= (gctUINT64) (high * 1000000) << 32;
7376 while (((gctINT64) b > 0) && (b < rem))
7395 return (gctUINT32) res;
7399 /******************************************************************************\
7400 ******************************* Signal Management ******************************
7401 \******************************************************************************/
7404 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
7406 /*******************************************************************************
7408 ** gckOS_CreateSignal
7410 ** Create a new signal.
7415 ** Pointer to an gckOS object.
7417 ** gctBOOL ManualReset
7418 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7419 ** order to set the signal to nonsignaled state.
7420 ** If set to gcvFALSE, the signal will automatically be set to
7421 ** nonsignaled state by gckOS_WaitSignal function.
7425 ** gctSIGNAL * Signal
7426 ** Pointer to a variable receiving the created gctSIGNAL.
7431 IN gctBOOL ManualReset,
7432 OUT gctSIGNAL * Signal
7436 gcsSIGNAL_PTR signal;
7438 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
7440 /* Verify the arguments. */
7441 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7442 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7444 /* Create an event structure. */
7445 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
7447 if (signal == gcvNULL)
7449 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7452 /* Save the process ID. */
7453 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
7454 signal->manualReset = ManualReset;
7455 signal->hardware = gcvNULL;
7456 init_completion(&signal->obj);
7457 atomic_set(&signal->ref, 1);
7459 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
7461 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
7463 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
7464 return gcvSTATUS_OK;
7467 if (signal != gcvNULL)
7477 gckOS_SignalQueryHardware(
7479 IN gctSIGNAL Signal,
7480 OUT gckHARDWARE * Hardware
7484 gcsSIGNAL_PTR signal;
7486 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7488 /* Verify the arguments. */
7489 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7490 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7491 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7493 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7495 *Hardware = signal->hardware;
7498 return gcvSTATUS_OK;
7505 gckOS_SignalSetHardware(
7507 IN gctSIGNAL Signal,
7508 IN gckHARDWARE Hardware
7512 gcsSIGNAL_PTR signal;
7514 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7516 /* Verify the arguments. */
7517 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7518 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7520 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7522 signal->hardware = Hardware;
7525 return gcvSTATUS_OK;
7531 /*******************************************************************************
7533 ** gckOS_DestroySignal
7535 ** Destroy a signal.
7540 ** Pointer to an gckOS object.
7543 ** Pointer to the gctSIGNAL.
7550 gckOS_DestroySignal(
7556 gcsSIGNAL_PTR signal;
7557 gctBOOL acquired = gcvFALSE;
7559 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7561 /* Verify the arguments. */
7562 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7563 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7565 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7568 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7570 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7572 if (atomic_dec_and_test(&signal->ref))
7574 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7576 /* Free the sgianl. */
7580 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7581 acquired = gcvFALSE;
7585 return gcvSTATUS_OK;
7590 /* Release the mutex. */
7591 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7598 /*******************************************************************************
7602 ** Set a state of the specified signal.
7607 ** Pointer to an gckOS object.
7610 ** Pointer to the gctSIGNAL.
7613 ** If gcvTRUE, the signal will be set to signaled state.
7614 ** If gcvFALSE, the signal will be set to nonsignaled state.
7623 IN gctSIGNAL Signal,
7628 gcsSIGNAL_PTR signal;
7629 gctBOOL acquired = gcvFALSE;
7631 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7633 /* Verify the arguments. */
7634 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7635 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7637 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7640 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7642 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7646 /* unbind the signal from hardware. */
7647 signal->hardware = gcvNULL;
7649 /* Set the event to a signaled state. */
7650 complete(&signal->obj);
7654 /* Set the event to an unsignaled state. */
7655 INIT_COMPLETION(signal->obj);
7658 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7659 acquired = gcvFALSE;
7663 return gcvSTATUS_OK;
7668 /* Release the mutex. */
7669 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7680 IN gctHANDLE Process,
7686 struct task_struct * userTask;
7687 struct siginfo info;
7689 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7691 if (userTask != gcvNULL)
7694 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7697 info.si_ptr = (gctPOINTER) Signal;
7699 /* Signals with numbers between 32 and 63 are real-time,
7700 send a real-time signal to the user process. */
7701 result = send_sig_info(48, &info, userTask);
7703 printk("gckOS_SetSignalVG:0x%x\n", result);
7707 status = gcvSTATUS_GENERIC_IO;
7711 "%s(%d): an error has occurred.\n",
7712 __FUNCTION__, __LINE__
7717 status = gcvSTATUS_OK;
7722 status = gcvSTATUS_GENERIC_IO;
7726 "%s(%d): an error has occurred.\n",
7727 __FUNCTION__, __LINE__
7731 /* Return status. */
7736 /*******************************************************************************
7740 ** Set the specified signal which is owned by a process to signaled state.
7745 ** Pointer to an gckOS object.
7748 ** Pointer to the gctSIGNAL.
7750 ** gctHANDLE Process
7751 ** Handle of process owning the signal.
7760 IN gctSIGNAL Signal,
7761 IN gctHANDLE Process
7767 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7768 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7770 /* Map the signal into kernel space. */
7771 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7774 status = gckOS_Signal(Os, signal, gcvTRUE);
7776 /* Unmap the signal */
7777 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7783 /* Return the status. */
7788 /*******************************************************************************
7792 ** Wait for a signal to become signaled.
7797 ** Pointer to an gckOS object.
7800 ** Pointer to the gctSIGNAL.
7803 ** Number of milliseconds to wait.
7804 ** Pass the value of gcvINFINITE for an infinite wait.
7813 IN gctSIGNAL Signal,
7817 gceSTATUS status = gcvSTATUS_OK;
7818 gcsSIGNAL_PTR signal;
7820 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7822 /* Verify the arguments. */
7823 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7824 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7826 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7828 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7832 spin_lock_irq(&signal->obj.wait.lock);
7834 if (signal->obj.done)
7836 if (!signal->manualReset)
7838 signal->obj.done = 0;
7841 status = gcvSTATUS_OK;
7845 status = gcvSTATUS_TIMEOUT;
7849 /* Convert wait to milliseconds. */
7850 #if gcdDETECT_TIMEOUT
7851 gctINT timeout = (Wait == gcvINFINITE)
7852 ? gcdINFINITE_TIMEOUT * HZ / 1000
7855 gctUINT complained = 0;
7857 gctINT timeout = (Wait == gcvINFINITE)
7858 ? MAX_SCHEDULE_TIMEOUT
7862 DECLARE_WAITQUEUE(wait, current);
7863 wait.flags |= WQ_FLAG_EXCLUSIVE;
7864 __add_wait_queue_tail(&signal->obj.wait, &wait);
7868 if (signal_pending(current))
7870 /* Interrupt received. */
7871 status = gcvSTATUS_INTERRUPTED;
7875 __set_current_state(TASK_INTERRUPTIBLE);
7876 spin_unlock_irq(&signal->obj.wait.lock);
7877 timeout = schedule_timeout(timeout);
7878 spin_lock_irq(&signal->obj.wait.lock);
7880 if (signal->obj.done)
7882 if (!signal->manualReset)
7884 signal->obj.done = 0;
7887 status = gcvSTATUS_OK;
7891 #if gcdDETECT_TIMEOUT
7892 if ((Wait == gcvINFINITE) && (timeout == 0))
7894 gctUINT32 dmaAddress1, dmaAddress2;
7895 gctUINT32 dmaState1, dmaState2;
7897 dmaState1 = dmaState2 =
7898 dmaAddress1 = dmaAddress2 = 0;
7900 /* Verify whether DMA is running. */
7901 gcmkVERIFY_OK(_VerifyDMA(
7902 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7905 #if gcdDETECT_DMA_ADDRESS
7906 /* Dump only if DMA appears stuck. */
7908 (dmaAddress1 == dmaAddress2)
7909 #if gcdDETECT_DMA_STATE
7910 && (dmaState1 == dmaState2)
7915 /* Increment complain count. */
7918 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
7921 "%s(%d): signal 0x%X; forced message flush (%d).",
7922 __FUNCTION__, __LINE__, Signal, complained
7925 /* Flush the debug cache. */
7926 gcmkDEBUGFLUSH(dmaAddress2);
7929 /* Reset timeout. */
7930 timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
7937 status = gcvSTATUS_TIMEOUT;
7942 __remove_wait_queue(&signal->obj.wait, &wait);
7944 #if gcdDETECT_TIMEOUT
7948 "%s(%d): signal=0x%X; waiting done; status=%d",
7949 __FUNCTION__, __LINE__, Signal, status
7955 spin_unlock_irq(&signal->obj.wait.lock);
7958 /* Return status. */
7959 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7963 /*******************************************************************************
7967 ** Map a signal in to the current process space.
7972 ** Pointer to an gckOS object.
7975 ** Pointer to tha gctSIGNAL to map.
7977 ** gctHANDLE Process
7978 ** Handle of process owning the signal.
7982 ** gctSIGNAL * MappedSignal
7983 ** Pointer to a variable receiving the mapped gctSIGNAL.
7988 IN gctSIGNAL Signal,
7989 IN gctHANDLE Process,
7990 OUT gctSIGNAL * MappedSignal
7994 gcsSIGNAL_PTR signal;
7995 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7997 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7998 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
8000 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
8002 if(atomic_inc_return(&signal->ref) <= 1)
8004 /* The previous value is 0, it has been deleted. */
8005 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
8008 *MappedSignal = (gctSIGNAL) Signal;
8011 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
8012 return gcvSTATUS_OK;
8019 /*******************************************************************************
8021 ** gckOS_UnmapSignal
8028 ** Pointer to an gckOS object.
8031 ** Pointer to that gctSIGNAL mapped.
8039 return gckOS_DestroySignal(Os, Signal);
8042 /*******************************************************************************
8044 ** gckOS_CreateUserSignal
8046 ** Create a new signal to be used in the user space.
8051 ** Pointer to an gckOS object.
8053 ** gctBOOL ManualReset
8054 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
8055 ** order to set the signal to nonsignaled state.
8056 ** If set to gcvFALSE, the signal will automatically be set to
8057 ** nonsignaled state by gckOS_WaitSignal function.
8061 ** gctINT * SignalID
8062 ** Pointer to a variable receiving the created signal's ID.
8065 gckOS_CreateUserSignal(
8067 IN gctBOOL ManualReset,
8068 OUT gctINT * SignalID
8074 /* Create a new signal. */
8075 status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
8076 *SignalID = (gctINT) signal;
8081 /*******************************************************************************
8083 ** gckOS_DestroyUserSignal
8085 ** Destroy a signal to be used in the user space.
8090 ** Pointer to an gckOS object.
8100 gckOS_DestroyUserSignal(
8105 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
8108 /*******************************************************************************
8110 ** gckOS_WaitUserSignal
8112 ** Wait for a signal used in the user mode to become signaled.
8117 ** Pointer to an gckOS object.
8123 ** Number of milliseconds to wait.
8124 ** Pass the value of gcvINFINITE for an infinite wait.
8131 gckOS_WaitUserSignal(
8137 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
8140 /*******************************************************************************
8142 ** gckOS_SignalUserSignal
8144 ** Set a state of the specified signal to be used in the user space.
8149 ** Pointer to an gckOS object.
8155 ** If gcvTRUE, the signal will be set to signaled state.
8156 ** If gcvFALSE, the signal will be set to nonsignaled state.
8163 gckOS_SignalUserSignal(
8169 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
8174 gckOS_CreateSemaphoreVG(
8176 OUT gctSEMAPHORE * Semaphore
8180 struct semaphore * newSemaphore;
8182 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8183 /* Verify the arguments. */
8184 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8185 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8189 /* Allocate the semaphore structure. */
8190 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
8191 if (newSemaphore == gcvNULL)
8193 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
8196 /* Initialize the semaphore. */
8197 sema_init(newSemaphore, 0);
8199 /* Set the handle. */
8200 * Semaphore = (gctSEMAPHORE) newSemaphore;
8203 status = gcvSTATUS_OK;
8208 /* Return the status. */
8214 gckOS_IncrementSemaphore(
8216 IN gctSEMAPHORE Semaphore
8219 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8220 /* Verify the arguments. */
8221 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8222 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8224 /* Increment the semaphore's count. */
8225 up((struct semaphore *) Semaphore);
8229 return gcvSTATUS_OK;
8233 gckOS_DecrementSemaphore(
8235 IN gctSEMAPHORE Semaphore
8241 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8242 /* Verify the arguments. */
8243 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8244 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8248 /* Decrement the semaphore's count. If the count is zero, wait
8249 until it gets incremented. */
8250 result = down_interruptible((struct semaphore *) Semaphore);
8252 /* Signal received? */
8255 status = gcvSTATUS_TERMINATE;
8260 status = gcvSTATUS_OK;
8265 /* Return the status. */
8269 /*******************************************************************************
8273 ** Set the specified signal to signaled state.
8278 ** Pointer to the gckOS object.
8280 ** gctHANDLE Process
8281 ** Handle of process owning the signal.
8284 ** Pointer to the gctSIGNAL.
8293 IN gctHANDLE Process,
8299 struct task_struct * userTask;
8300 struct siginfo info;
8302 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
8304 if (userTask != gcvNULL)
8307 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
8310 info.si_ptr = (gctPOINTER) Signal;
8312 /* Signals with numbers between 32 and 63 are real-time,
8313 send a real-time signal to the user process. */
8314 result = send_sig_info(48, &info, userTask);
8319 status = gcvSTATUS_GENERIC_IO;
8323 "%s(%d): an error has occurred.\n",
8324 __FUNCTION__, __LINE__
8329 status = gcvSTATUS_OK;
8334 status = gcvSTATUS_GENERIC_IO;
8338 "%s(%d): an error has occurred.\n",
8339 __FUNCTION__, __LINE__
8343 /* Return status. */
8347 /******************************************************************************\
8348 ******************************** Thread Object *********************************
8349 \******************************************************************************/
8354 IN gctTHREADFUNC ThreadFunction,
8355 IN gctPOINTER ThreadParameter,
8356 OUT gctTHREAD * Thread
8360 struct task_struct * thread;
8362 gcmkHEADER_ARG("Os=0x%X ", Os);
8363 /* Verify the arguments. */
8364 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8365 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
8366 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8370 /* Create the thread. */
8371 thread = kthread_create(
8374 "Vivante Kernel Thread"
8380 status = gcvSTATUS_GENERIC_IO;
8384 /* Start the thread. */
8385 wake_up_process(thread);
8387 /* Set the thread handle. */
8388 * Thread = (gctTHREAD) thread;
8391 status = gcvSTATUS_OK;
8396 /* Return the status. */
8406 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8407 /* Verify the arguments. */
8408 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8409 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8411 /* Thread should have already been enabled to terminate. */
8412 kthread_stop((struct task_struct *) Thread);
8416 return gcvSTATUS_OK;
8425 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8426 /* Verify the arguments. */
8427 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8428 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8432 return gcvSTATUS_OK;
8436 /******************************************************************************\
8437 ******************************** Software Timer ********************************
8438 \******************************************************************************/
8442 struct work_struct * work
8445 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
8447 gctTIMERFUNCTION function = timer->function;
8449 function(timer->data);
8452 /*******************************************************************************
8454 ** gckOS_CreateTimer
8456 ** Create a software timer.
8461 ** Pointer to the gckOS object.
8463 ** gctTIMERFUNCTION Function.
8464 ** Pointer to a call back function which will be called when timer is
8468 ** Private data which will be passed to call back function.
8472 ** gctPOINTER * Timer
8473 ** Pointer to a variable receiving the created timer.
8478 IN gctTIMERFUNCTION Function,
8480 OUT gctPOINTER * Timer
8484 gcsOSTIMER_PTR pointer;
8485 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
8487 /* Verify the arguments. */
8488 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8489 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8491 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
8493 pointer->function = Function;
8494 pointer->data = Data;
8496 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
8501 return gcvSTATUS_OK;
8508 /*******************************************************************************
8510 ** gckOS_DestroyTimer
8512 ** Destory a software timer.
8517 ** Pointer to the gckOS object.
8520 ** Pointer to the timer to be destoryed.
8532 gcsOSTIMER_PTR timer;
8533 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8535 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8536 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8538 timer = (gcsOSTIMER_PTR)Timer;
8540 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8541 cancel_delayed_work_sync(&timer->work);
8543 cancel_delayed_work(&timer->work);
8544 flush_workqueue(Os->workqueue);
8547 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8550 return gcvSTATUS_OK;
8553 /*******************************************************************************
8557 ** Schedule a software timer.
8562 ** Pointer to the gckOS object.
8565 ** Pointer to the timer to be scheduled.
8568 ** Delay in milliseconds.
8577 IN gctPOINTER Timer,
8581 gcsOSTIMER_PTR timer;
8583 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8585 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8586 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8587 gcmkVERIFY_ARGUMENT(Delay != 0);
8589 timer = (gcsOSTIMER_PTR)Timer;
8591 if (unlikely(delayed_work_pending(&timer->work)))
8593 if (unlikely(!cancel_delayed_work(&timer->work)))
8595 cancel_work_sync(&timer->work.work);
8597 if (unlikely(delayed_work_pending(&timer->work)))
8599 gckOS_Print("gckOS_StartTimer error, the pending worker cannot complete!!!! \n");
8601 return gcvSTATUS_INVALID_REQUEST;
8606 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8609 return gcvSTATUS_OK;
8612 /*******************************************************************************
8616 ** Cancel a unscheduled timer.
8621 ** Pointer to the gckOS object.
8624 ** Pointer to the timer to be cancel.
8636 gcsOSTIMER_PTR timer;
8637 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8639 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8640 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8642 timer = (gcsOSTIMER_PTR)Timer;
8644 cancel_delayed_work(&timer->work);
8647 return gcvSTATUS_OK;
8652 gckOS_DumpCallStack(
8656 gcmkHEADER_ARG("Os=0x%X", Os);
8658 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8663 return gcvSTATUS_OK;
8668 gckOS_GetProcessNameByPid(
8670 IN gctSIZE_T Length,
8671 OUT gctUINT8_PTR String
8674 struct task_struct *task;
8676 /* Get the task_struct of the task with pid. */
8679 task = FIND_TASK_BY_PID(Pid);
8681 if (task == gcvNULL)
8684 return gcvSTATUS_NOT_FOUND;
8687 /* Get name of process. */
8688 strncpy(String, task->comm, Length);
8692 return gcvSTATUS_OK;
8695 #if gcdANDROID_NATIVE_FENCE_SYNC
8698 gckOS_CreateSyncPoint(
8700 OUT gctSYNC_POINT * SyncPoint
8704 gcsSYNC_POINT_PTR syncPoint;
8706 gcmkHEADER_ARG("Os=0x%X", Os);
8708 /* Verify the arguments. */
8709 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8711 /* Create an sync point structure. */
8712 syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
8713 sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
8715 if (syncPoint == gcvNULL)
8717 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8720 /* Initialize the sync point. */
8721 atomic_set(&syncPoint->ref, 1);
8722 atomic_set(&syncPoint->state, 0);
8724 gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
8726 *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
8728 gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
8729 return gcvSTATUS_OK;
8732 if (syncPoint != gcvNULL)
8742 gckOS_ReferenceSyncPoint(
8744 IN gctSYNC_POINT SyncPoint
8748 gcsSYNC_POINT_PTR syncPoint;
8750 gcmkHEADER_ARG("Os=0x%X", Os);
8752 /* Verify the arguments. */
8753 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8754 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8757 _QueryIntegerId(&Os->syncPointDB,
8758 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8759 (gctPOINTER)&syncPoint));
8761 /* Initialize the sync point. */
8762 atomic_inc(&syncPoint->ref);
8765 return gcvSTATUS_OK;
8773 gckOS_DestroySyncPoint(
8775 IN gctSYNC_POINT SyncPoint
8779 gcsSYNC_POINT_PTR syncPoint;
8780 gctBOOL acquired = gcvFALSE;
8782 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8784 /* Verify the arguments. */
8785 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8786 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8788 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8792 _QueryIntegerId(&Os->syncPointDB,
8793 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8794 (gctPOINTER)&syncPoint));
8796 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8798 if (atomic_dec_and_test(&syncPoint->ref))
8800 gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
8802 /* Free the sgianl. */
8803 syncPoint->timeline = gcvNULL;
8807 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8808 acquired = gcvFALSE;
8812 return gcvSTATUS_OK;
8817 /* Release the mutex. */
8818 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8826 gckOS_SignalSyncPoint(
8828 IN gctSYNC_POINT SyncPoint
8832 gcsSYNC_POINT_PTR syncPoint;
8833 gctBOOL acquired = gcvFALSE;
8835 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8837 /* Verify the arguments. */
8838 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8839 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8841 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8845 _QueryIntegerId(&Os->syncPointDB,
8846 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8847 (gctPOINTER)&syncPoint));
8849 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8852 atomic_set(&syncPoint->state, gcvTRUE);
8854 /* Signal timeline. */
8855 if (syncPoint->timeline)
8857 sync_timeline_signal(syncPoint->timeline);
8860 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8861 acquired = gcvFALSE;
8865 return gcvSTATUS_OK;
8870 /* Release the mutex. */
8871 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8879 gckOS_QuerySyncPoint(
8881 IN gctSYNC_POINT SyncPoint,
8882 OUT gctBOOL_PTR State
8886 gcsSYNC_POINT_PTR syncPoint;
8888 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8890 /* Verify the arguments. */
8891 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8892 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8895 _QueryIntegerId(&Os->syncPointDB,
8896 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8897 (gctPOINTER)&syncPoint));
8899 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8902 *State = atomic_read(&syncPoint->state);
8905 gcmkFOOTER_ARG("*State=%d", *State);
8906 return gcvSTATUS_OK;
8914 gckOS_CreateSyncTimeline(
8916 OUT gctHANDLE * Timeline
8919 struct viv_sync_timeline * timeline;
8921 /* Create viv sync timeline. */
8922 timeline = viv_sync_timeline_create("viv timeline", Os);
8924 if (timeline == gcvNULL)
8926 /* Out of memory. */
8927 return gcvSTATUS_OUT_OF_MEMORY;
8930 *Timeline = (gctHANDLE) timeline;
8931 return gcvSTATUS_OK;
8935 gckOS_DestroySyncTimeline(
8937 IN gctHANDLE Timeline
8940 struct viv_sync_timeline * timeline;
8941 gcmkASSERT(Timeline != gcvNULL);
8943 /* Destroy timeline. */
8944 timeline = (struct viv_sync_timeline *) Timeline;
8945 sync_timeline_destroy(&timeline->obj);
8947 return gcvSTATUS_OK;
8951 gckOS_CreateNativeFence(
8953 IN gctHANDLE Timeline,
8954 IN gctSYNC_POINT SyncPoint,
8955 OUT gctINT * FenceFD
8959 struct viv_sync_timeline *timeline;
8960 struct sync_pt * pt = gcvNULL;
8961 struct sync_fence * fence;
8963 gcsSYNC_POINT_PTR syncPoint;
8966 gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
8967 Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
8970 _QueryIntegerId(&Os->syncPointDB,
8971 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8972 (gctPOINTER)&syncPoint));
8974 /* Cast timeline. */
8975 timeline = (struct viv_sync_timeline *) Timeline;
8977 fd = get_unused_fd();
8981 /* Out of resources. */
8982 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
8985 /* Create viv_sync_pt. */
8986 pt = viv_sync_pt_create(timeline, SyncPoint);
8990 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8993 /* Reference sync_timeline. */
8994 syncPoint->timeline = &timeline->obj;
8996 /* Build fence name. */
8997 snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
8999 /* Create sync_fence. */
9000 fence = sync_fence_create(name, pt);
9004 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
9007 /* Install fence to fd. */
9008 sync_fence_install(fence, fd);
9011 gcmkFOOTER_ARG("*FenceFD=%d", fd);
9012 return gcvSTATUS_OK;
9015 /* Error roll back. */