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;
382 mdlMap->next = Mdl->maps;
385 gcmkFOOTER_ARG("0x%X", mdlMap);
392 IN PLINUX_MDL_MAP MdlMap
395 PLINUX_MDL_MAP prevMdlMap;
397 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
399 /* Verify the arguments. */
400 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
401 gcmkASSERT(Mdl->maps != gcvNULL);
403 if (Mdl->maps == MdlMap)
405 Mdl->maps = MdlMap->next;
409 prevMdlMap = Mdl->maps;
411 while (prevMdlMap->next != MdlMap)
413 prevMdlMap = prevMdlMap->next;
415 gcmkASSERT(prevMdlMap != gcvNULL);
418 prevMdlMap->next = MdlMap->next;
427 extern PLINUX_MDL_MAP
433 PLINUX_MDL_MAP mdlMap;
435 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
443 while (mdlMap != gcvNULL)
445 if (mdlMap->pid == ProcessID)
447 gcmkFOOTER_ARG("0x%X", mdlMap);
451 mdlMap = mdlMap->next;
466 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
472 unsigned long addr = (unsigned long)Addr;
474 return addr >= VMALLOC_START && addr < VMALLOC_END;
480 IN struct page ** Pages,
481 IN gctUINT32 NumPages
486 gcmkHEADER_ARG("Pages=0x%X, NumPages=%d", Pages, NumPages);
488 gcmkASSERT(Pages != gcvNULL);
490 for (i = 0; i < NumPages; i++)
492 __free_page(Pages[i]);
495 if (is_vmalloc_addr(Pages))
507 static struct page **
509 IN gctUINT32 NumPages
512 struct page ** pages;
516 gcmkHEADER_ARG("NumPages=%lu", NumPages);
518 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 32)
519 if (NumPages > totalram_pages)
521 if (NumPages > num_physpages)
528 size = NumPages * sizeof(struct page *);
530 pages = kmalloc(size, GFP_KERNEL | gcdNOWARN);
534 pages = vmalloc(size);
543 for (i = 0; i < NumPages; i++)
545 p = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
549 _NonContiguousFree(pages, i);
557 gcmkFOOTER_ARG("pages=0x%X", pages);
561 static inline struct page *
562 _NonContiguousToPage(
563 IN struct page ** Pages,
567 gcmkASSERT(Pages != gcvNULL);
571 static inline unsigned long
573 IN struct page ** Pages,
577 gcmkASSERT(Pages != gcvNULL);
578 return page_to_pfn(_NonContiguousToPage(Pages, Index));
581 static inline unsigned long
582 _NonContiguousToPhys(
583 IN struct page ** Pages,
587 gcmkASSERT(Pages != gcvNULL);
588 return page_to_phys(_NonContiguousToPage(Pages, Index));
592 #if gcdUSE_NON_PAGED_MEMORY_CACHE
595 _AddNonPagedMemoryCache(
597 #ifndef NO_DMA_COHERENT
607 gcsNonPagedMemoryCache *cache;
609 if (Os->cacheSize >= gcdUSE_NON_PAGED_MEMORY_CACHE)
614 /* Allocate the cache record */
615 cache = (gcsNonPagedMemoryCache *)kmalloc(sizeof(gcsNonPagedMemoryCache), GFP_ATOMIC);
617 if (cache == gcvNULL) return gcvFALSE;
619 #ifndef NO_DMA_COHERENT
622 cache->dmaHandle = DmaHandle;
624 cache->order = Order;
629 if (Os->cacheHead == gcvNULL)
631 cache->prev = gcvNULL;
632 cache->next = gcvNULL;
634 Os->cacheTail = cache;
638 /* Add to the tail. */
639 cache->prev = Os->cacheTail;
640 cache->next = gcvNULL;
641 Os->cacheTail->next = cache;
642 Os->cacheTail = cache;
650 #ifndef NO_DMA_COHERENT
652 _GetNonPagedMemoryCache(
655 dma_addr_t * DmaHandle
659 _GetNonPagedMemoryCache(
665 gcsNonPagedMemoryCache *cache;
666 #ifndef NO_DMA_COHERENT
672 if (Os->cacheHead == gcvNULL) return gcvNULL;
674 /* Find the right cache */
675 cache = Os->cacheHead;
677 while (cache != gcvNULL)
679 #ifndef NO_DMA_COHERENT
680 if (cache->size == Size) break;
682 if (cache->order == Order) break;
688 if (cache == gcvNULL) return gcvNULL;
690 /* Remove the cache from list */
691 if (cache == Os->cacheHead)
693 Os->cacheHead = cache->next;
695 if (Os->cacheHead == gcvNULL)
697 Os->cacheTail = gcvNULL;
702 cache->prev->next = cache->next;
704 if (cache == Os->cacheTail)
706 Os->cacheTail = cache->prev;
710 cache->next->prev = cache->prev;
715 #ifndef NO_DMA_COHERENT
717 *DmaHandle = cache->dmaHandle;
726 #ifndef NO_DMA_COHERENT
734 _FreeAllNonPagedMemoryCache(
738 gcsNonPagedMemoryCache *cache, *nextCache;
742 cache = Os->cacheHead;
744 while (cache != gcvNULL)
746 if (cache != Os->cacheTail)
748 nextCache = cache->next;
755 /* Remove the cache from list */
756 if (cache == Os->cacheHead)
758 Os->cacheHead = cache->next;
760 if (Os->cacheHead == gcvNULL)
762 Os->cacheTail = gcvNULL;
767 cache->prev->next = cache->next;
769 if (cache == Os->cacheTail)
771 Os->cacheTail = cache->prev;
775 cache->next->prev = cache->prev;
779 #ifndef NO_DMA_COHERENT
780 dma_free_coherent(gcvNULL,
785 free_pages((unsigned long)page_address(cache->page), cache->order);
796 #endif /* gcdUSE_NON_PAGED_MEMORY_CACHE */
798 /*******************************************************************************
799 ** Integer Id Management.
803 IN gcsINTEGER_DB_PTR Database,
804 IN gctPOINTER KernelPointer,
811 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
812 idr_preload(GFP_KERNEL | gcdNOWARN);
814 spin_lock(&Database->lock);
816 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
817 result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
821 Database->curr = *Id;
824 spin_unlock(&Database->lock);
830 return gcvSTATUS_OUT_OF_RESOURCES;
836 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
838 return gcvSTATUS_OUT_OF_MEMORY;
841 spin_lock(&Database->lock);
843 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
845 /* Try to get a id greater than current id. */
846 result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
850 Database->curr = *Id;
853 spin_unlock(&Database->lock);
855 if (result == -EAGAIN)
862 return gcvSTATUS_OUT_OF_RESOURCES;
871 IN gcsINTEGER_DB_PTR Database,
873 OUT gctPOINTER * KernelPointer
878 spin_lock(&Database->lock);
880 pointer = idr_find(&Database->idr, Id);
882 spin_unlock(&Database->lock);
886 *KernelPointer = pointer;
892 gcvLEVEL_ERROR, gcvZONE_OS,
893 "%s(%d) Id = %d is not found",
894 __FUNCTION__, __LINE__, Id);
896 return gcvSTATUS_NOT_FOUND;
902 IN gcsINTEGER_DB_PTR Database,
906 spin_lock(&Database->lock);
908 idr_remove(&Database->idr, Id);
910 spin_unlock(&Database->lock);
918 IN gctPOINTER Logical,
922 if (unlikely(current->mm == gcvNULL))
924 /* Do nothing if process is exiting. */
928 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
929 if (vm_munmap((unsigned long)Logical, Size) < 0)
932 gcvLEVEL_WARNING, gcvZONE_OS,
933 "%s(%d): vm_munmap failed",
934 __FUNCTION__, __LINE__
938 down_write(¤t->mm->mmap_sem);
939 if (do_munmap(current->mm, (unsigned long)Logical, Size) < 0)
942 gcvLEVEL_WARNING, gcvZONE_OS,
943 "%s(%d): do_munmap failed",
944 __FUNCTION__, __LINE__
947 up_write(¤t->mm->mmap_sem);
952 _QueryProcessPageTable(
953 IN gctPOINTER Logical,
954 OUT gctUINT32 * Address
958 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
966 return gcvSTATUS_NOT_FOUND;
969 pgd = pgd_offset(current->mm, logical);
970 if (pgd_none(*pgd) || pgd_bad(*pgd))
972 return gcvSTATUS_NOT_FOUND;
975 pud = pud_offset(pgd, logical);
976 if (pud_none(*pud) || pud_bad(*pud))
978 return gcvSTATUS_NOT_FOUND;
981 pmd = pmd_offset(pud, logical);
982 if (pmd_none(*pmd) || pmd_bad(*pmd))
984 return gcvSTATUS_NOT_FOUND;
987 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
990 return gcvSTATUS_NOT_FOUND;
993 if (!pte_present(*pte))
995 pte_unmap_unlock(pte, lock);
996 return gcvSTATUS_NOT_FOUND;
999 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
1000 pte_unmap_unlock(pte, lock);
1002 return gcvSTATUS_OK;
1005 /*******************************************************************************
1009 ** Construct a new gckOS object.
1013 ** gctPOINTER Context
1014 ** Pointer to the gckGALDEVICE class.
1019 ** Pointer to a variable that will hold the pointer to the gckOS object.
1023 IN gctPOINTER Context,
1030 gcmkHEADER_ARG("Context=0x%X", Context);
1032 /* Verify the arguments. */
1033 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
1035 /* Allocate the gckOS object. */
1036 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
1040 /* Out of memory. */
1041 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1042 return gcvSTATUS_OUT_OF_MEMORY;
1045 /* Zero the memory. */
1046 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
1048 /* Initialize the gckOS object. */
1049 os->object.type = gcvOBJ_OS;
1051 /* Set device device. */
1052 os->device = Context;
1054 /* IMPORTANT! No heap yet. */
1057 /* Initialize the memory lock. */
1058 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
1059 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
1061 /* Create debug lock mutex. */
1062 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
1065 os->mdlHead = os->mdlTail = gcvNULL;
1067 /* Get the kernel process ID. */
1068 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
1071 * Initialize the signal manager.
1074 /* Initialize mutex. */
1075 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
1077 /* Initialize signal id database lock. */
1078 spin_lock_init(&os->signalDB.lock);
1080 /* Initialize signal id database. */
1081 idr_init(&os->signalDB.idr);
1083 #if gcdANDROID_NATIVE_FENCE_SYNC
1085 * Initialize the sync point manager.
1088 /* Initialize mutex. */
1089 gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
1091 /* Initialize sync point id database lock. */
1092 spin_lock_init(&os->syncPointDB.lock);
1094 /* Initialize sync point id database. */
1095 idr_init(&os->syncPointDB.idr);
1098 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1100 os->cacheHead = gcvNULL;
1101 os->cacheTail = gcvNULL;
1104 /* Create a workqueue for os timer. */
1105 os->workqueue = create_singlethread_workqueue("galcore workqueue");
1107 if (os->workqueue == gcvNULL)
1109 /* Out of memory. */
1110 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1113 /* Return pointer to the gckOS object. */
1117 gcmkFOOTER_ARG("*Os=0x%X", *Os);
1118 return gcvSTATUS_OK;
1122 #if gcdANDROID_NATIVE_FENCE_SYNC
1123 if (os->syncPointMutex != gcvNULL)
1126 gckOS_DeleteMutex(os, os->syncPointMutex));
1130 if (os->signalMutex != gcvNULL)
1133 gckOS_DeleteMutex(os, os->signalMutex));
1136 if (os->heap != gcvNULL)
1139 gckHEAP_Destroy(os->heap));
1142 if (os->memoryMapLock != gcvNULL)
1145 gckOS_DeleteMutex(os, os->memoryMapLock));
1148 if (os->memoryLock != gcvNULL)
1151 gckOS_DeleteMutex(os, os->memoryLock));
1154 if (os->debugLock != gcvNULL)
1157 gckOS_DeleteMutex(os, os->debugLock));
1160 if (os->workqueue != gcvNULL)
1162 destroy_workqueue(os->workqueue);
1167 /* Return the error. */
1172 /*******************************************************************************
1176 ** Destroy an gckOS object.
1181 ** Pointer to an gckOS object that needs to be destroyed.
1194 gcmkHEADER_ARG("Os=0x%X", Os);
1196 /* Verify the arguments. */
1197 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1199 #if gcdUSE_NON_PAGED_MEMORY_CACHE
1200 _FreeAllNonPagedMemoryCache(Os);
1203 #if gcdANDROID_NATIVE_FENCE_SYNC
1205 * Destroy the sync point manager.
1208 /* Destroy the mutex. */
1209 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
1213 * Destroy the signal manager.
1216 /* Destroy the mutex. */
1217 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
1219 if (Os->heap != gcvNULL)
1221 /* Mark gckHEAP as gone. */
1225 /* Destroy the gckHEAP object. */
1226 gcmkVERIFY_OK(gckHEAP_Destroy(heap));
1229 /* Destroy the memory lock. */
1230 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
1231 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
1233 /* Destroy debug lock mutex. */
1234 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
1236 /* Wait for all works done. */
1237 flush_workqueue(Os->workqueue);
1239 /* Destory work queue. */
1240 destroy_workqueue(Os->workqueue);
1242 /* Flush the debug cache. */
1243 gcmkDEBUGFLUSH(~0U);
1245 /* Mark the gckOS object as unknown. */
1246 Os->object.type = gcvOBJ_UNKNOWN;
1248 /* Free the gckOS object. */
1253 return gcvSTATUS_OK;
1257 _CreateKernelVirtualMapping(
1262 gctINT numPages = Mdl->numPages;
1264 #if gcdNONPAGED_MEMORY_CACHEABLE
1265 if (Mdl->contiguous)
1267 addr = page_address(Mdl->u.contiguousPages);
1271 addr = vmap(Mdl->u.nonContiguousPages,
1276 /* Trigger a page fault. */
1277 memset(addr, 0, numPages * PAGE_SIZE);
1280 struct page ** pages;
1281 gctBOOL free = gcvFALSE;
1284 if (Mdl->contiguous)
1286 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
1293 for (i = 0; i < numPages; i++)
1295 pages[i] = nth_page(Mdl->u.contiguousPages, i);
1302 pages = Mdl->u.nonContiguousPages;
1305 /* ioremap() can't work on system memory since 2.6.38. */
1306 addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
1308 /* Trigger a page fault. */
1309 memset(addr, 0, numPages * PAGE_SIZE);
1322 _DestoryKernelVirtualMapping(
1326 #if !gcdNONPAGED_MEMORY_CACHEABLE
1332 gckOS_CreateKernelVirtualMapping(
1333 IN gctPHYS_ADDR Physical,
1334 OUT gctSIZE_T * PageCount,
1335 OUT gctPOINTER * Logical
1338 *PageCount = ((PLINUX_MDL)Physical)->numPages;
1339 *Logical = _CreateKernelVirtualMapping((PLINUX_MDL)Physical);
1341 return gcvSTATUS_OK;
1345 gckOS_DestroyKernelVirtualMapping(
1346 IN gctPOINTER Logical
1349 _DestoryKernelVirtualMapping((gctSTRING)Logical);
1350 return gcvSTATUS_OK;
1353 /*******************************************************************************
1362 ** Pointer to an gckOS object.
1365 ** Number of bytes to allocate.
1369 ** gctPOINTER * Memory
1370 ** Pointer to a variable that will hold the allocated memory location.
1376 OUT gctPOINTER * Memory
1381 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1383 /* Verify the arguments. */
1384 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1385 gcmkVERIFY_ARGUMENT(Bytes > 0);
1386 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1388 /* Do we have a heap? */
1389 if (Os->heap != gcvNULL)
1391 /* Allocate from the heap. */
1392 gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
1396 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
1400 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1401 return gcvSTATUS_OK;
1404 /* Return the status. */
1409 /*******************************************************************************
1413 ** Free allocated memory.
1418 ** Pointer to an gckOS object.
1420 ** gctPOINTER Memory
1421 ** Pointer to memory allocation to free.
1430 IN gctPOINTER Memory
1435 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
1437 /* Verify the arguments. */
1438 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1439 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1441 /* Do we have a heap? */
1442 if (Os->heap != gcvNULL)
1444 /* Free from the heap. */
1445 gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
1449 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1454 return gcvSTATUS_OK;
1457 /* Return the status. */
1462 /*******************************************************************************
1464 ** gckOS_AllocateMemory
1466 ** Allocate memory wrapper.
1471 ** Number of bytes to allocate.
1475 ** gctPOINTER * Memory
1476 ** Pointer to a variable that will hold the allocated memory location.
1479 gckOS_AllocateMemory(
1482 OUT gctPOINTER * Memory
1488 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1490 /* Verify the arguments. */
1491 gcmkVERIFY_ARGUMENT(Bytes > 0);
1492 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1494 if (Bytes > PAGE_SIZE)
1496 memory = (gctPOINTER) vmalloc(Bytes);
1500 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1503 if (memory == gcvNULL)
1505 /* Out of memory. */
1506 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1509 /* Return pointer to the memory allocation. */
1513 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1514 return gcvSTATUS_OK;
1517 /* Return the status. */
1522 /*******************************************************************************
1526 ** Free allocated memory wrapper.
1530 ** gctPOINTER Memory
1531 ** Pointer to memory allocation to free.
1540 IN gctPOINTER Memory
1543 gcmkHEADER_ARG("Memory=0x%X", Memory);
1545 /* Verify the arguments. */
1546 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1548 /* Free the memory from the OS pool. */
1549 if (is_vmalloc_addr(Memory))
1560 return gcvSTATUS_OK;
1563 /*******************************************************************************
1567 ** Map physical memory into the current process.
1572 ** Pointer to an gckOS object.
1574 ** gctPHYS_ADDR Physical
1575 ** Start of physical address memory.
1578 ** Number of bytes to map.
1582 ** gctPOINTER * Memory
1583 ** Pointer to a variable that will hold the logical address of the
1589 IN gctPHYS_ADDR Physical,
1591 OUT gctPOINTER * Logical
1594 PLINUX_MDL_MAP mdlMap;
1595 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1597 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1599 /* Verify the arguments. */
1600 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1601 gcmkVERIFY_ARGUMENT(Physical != 0);
1602 gcmkVERIFY_ARGUMENT(Bytes > 0);
1603 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1607 mdlMap = FindMdlMap(mdl, _GetProcessID());
1609 if (mdlMap == gcvNULL)
1611 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1613 if (mdlMap == gcvNULL)
1617 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1618 return gcvSTATUS_OUT_OF_MEMORY;
1622 if (mdlMap->vmaAddr == gcvNULL)
1624 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1625 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1627 mdl->numPages * PAGE_SIZE,
1628 PROT_READ | PROT_WRITE,
1632 down_write(¤t->mm->mmap_sem);
1634 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1636 mdl->numPages * PAGE_SIZE,
1637 PROT_READ | PROT_WRITE,
1641 up_write(¤t->mm->mmap_sem);
1644 if (IS_ERR(mdlMap->vmaAddr))
1648 "%s(%d): do_mmap_pgoff error",
1649 __FUNCTION__, __LINE__
1654 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1655 __FUNCTION__, __LINE__,
1660 mdlMap->vmaAddr = gcvNULL;
1664 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1665 return gcvSTATUS_OUT_OF_MEMORY;
1668 down_write(¤t->mm->mmap_sem);
1670 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1676 "%s(%d): find_vma error.",
1677 __FUNCTION__, __LINE__
1680 mdlMap->vmaAddr = gcvNULL;
1682 up_write(¤t->mm->mmap_sem);
1686 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1687 return gcvSTATUS_OUT_OF_RESOURCES;
1690 #ifndef NO_DMA_COHERENT
1691 if (dma_mmap_coherent(gcvNULL,
1695 mdl->numPages * PAGE_SIZE) < 0)
1697 up_write(¤t->mm->mmap_sem);
1701 "%s(%d): dma_mmap_coherent error.",
1702 __FUNCTION__, __LINE__
1705 mdlMap->vmaAddr = gcvNULL;
1709 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1710 return gcvSTATUS_OUT_OF_RESOURCES;
1713 #if !gcdPAGED_MEMORY_CACHEABLE
1714 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1715 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1717 mdlMap->vma->vm_pgoff = 0;
1719 if (remap_pfn_range(mdlMap->vma,
1720 mdlMap->vma->vm_start,
1721 mdl->dmaHandle >> PAGE_SHIFT,
1722 mdl->numPages*PAGE_SIZE,
1723 mdlMap->vma->vm_page_prot) < 0)
1725 up_write(¤t->mm->mmap_sem);
1729 "%s(%d): remap_pfn_range error.",
1730 __FUNCTION__, __LINE__
1733 mdlMap->vmaAddr = gcvNULL;
1737 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1738 return gcvSTATUS_OUT_OF_RESOURCES;
1742 up_write(¤t->mm->mmap_sem);
1747 *Logical = mdlMap->vmaAddr;
1749 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1750 return gcvSTATUS_OK;
1753 /*******************************************************************************
1755 ** gckOS_UnmapMemory
1757 ** Unmap physical memory out of the current process.
1762 ** Pointer to an gckOS object.
1764 ** gctPHYS_ADDR Physical
1765 ** Start of physical address memory.
1768 ** Number of bytes to unmap.
1770 ** gctPOINTER Memory
1771 ** Pointer to a previously mapped memory region.
1780 IN gctPHYS_ADDR Physical,
1782 IN gctPOINTER Logical
1785 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1786 Os, Physical, Bytes, Logical);
1788 /* Verify the arguments. */
1789 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1790 gcmkVERIFY_ARGUMENT(Physical != 0);
1791 gcmkVERIFY_ARGUMENT(Bytes > 0);
1792 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1794 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1798 return gcvSTATUS_OK;
1802 /*******************************************************************************
1804 ** gckOS_UnmapMemoryEx
1806 ** Unmap physical memory in the specified process.
1811 ** Pointer to an gckOS object.
1813 ** gctPHYS_ADDR Physical
1814 ** Start of physical address memory.
1817 ** Number of bytes to unmap.
1819 ** gctPOINTER Memory
1820 ** Pointer to a previously mapped memory region.
1823 ** Pid of the process that opened the device and mapped this memory.
1830 gckOS_UnmapMemoryEx(
1832 IN gctPHYS_ADDR Physical,
1834 IN gctPOINTER Logical,
1838 PLINUX_MDL_MAP mdlMap;
1839 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1841 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1842 Os, Physical, Bytes, Logical, PID);
1844 /* Verify the arguments. */
1845 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1846 gcmkVERIFY_ARGUMENT(Physical != 0);
1847 gcmkVERIFY_ARGUMENT(Bytes > 0);
1848 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1849 gcmkVERIFY_ARGUMENT(PID != 0);
1855 mdlMap = FindMdlMap(mdl, PID);
1857 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1861 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1862 return gcvSTATUS_INVALID_ARGUMENT;
1865 _UnmapUserLogical(PID, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1867 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1874 return gcvSTATUS_OK;
1877 /*******************************************************************************
1879 ** gckOS_UnmapUserLogical
1881 ** Unmap user logical memory out of physical memory.
1886 ** Pointer to an gckOS object.
1888 ** gctPHYS_ADDR Physical
1889 ** Start of physical address memory.
1892 ** Number of bytes to unmap.
1894 ** gctPOINTER Memory
1895 ** Pointer to a previously mapped memory region.
1902 gckOS_UnmapUserLogical(
1904 IN gctPHYS_ADDR Physical,
1906 IN gctPOINTER Logical
1909 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1910 Os, Physical, Bytes, Logical);
1912 /* Verify the arguments. */
1913 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1914 gcmkVERIFY_ARGUMENT(Physical != 0);
1915 gcmkVERIFY_ARGUMENT(Bytes > 0);
1916 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1918 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1922 return gcvSTATUS_OK;
1926 /*******************************************************************************
1928 ** gckOS_AllocateNonPagedMemory
1930 ** Allocate a number of pages from non-paged memory.
1935 ** Pointer to an gckOS object.
1937 ** gctBOOL InUserSpace
1938 ** gcvTRUE if the pages need to be mapped into user space.
1940 ** gctSIZE_T * Bytes
1941 ** Pointer to a variable that holds the number of bytes to allocate.
1945 ** gctSIZE_T * Bytes
1946 ** Pointer to a variable that hold the number of bytes allocated.
1948 ** gctPHYS_ADDR * Physical
1949 ** Pointer to a variable that will hold the physical address of the
1952 ** gctPOINTER * Logical
1953 ** Pointer to a variable that will hold the logical address of the
1957 gckOS_AllocateNonPagedMemory(
1959 IN gctBOOL InUserSpace,
1960 IN OUT gctSIZE_T * Bytes,
1961 OUT gctPHYS_ADDR * Physical,
1962 OUT gctPOINTER * Logical
1967 PLINUX_MDL mdl = gcvNULL;
1968 PLINUX_MDL_MAP mdlMap = gcvNULL;
1970 #ifdef NO_DMA_COHERENT
1975 gctBOOL locked = gcvFALSE;
1978 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1979 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1981 /* Verify the arguments. */
1982 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1983 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1984 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1985 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1986 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1988 /* Align number of bytes to page size. */
1989 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1991 /* Get total number of pages.. */
1992 numPages = GetPageCount(bytes, 0);
1994 /* Allocate mdl+vector structure */
1995 mdl = _CreateMdl(_GetProcessID());
1998 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2002 mdl->numPages = numPages;
2007 #ifndef NO_DMA_COHERENT
2008 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2009 addr = _GetNonPagedMemoryCache(Os,
2010 mdl->numPages * PAGE_SIZE,
2013 if (addr == gcvNULL)
2016 addr = dma_alloc_coherent(gcvNULL,
2017 mdl->numPages * PAGE_SIZE,
2019 GFP_KERNEL | gcdNOWARN);
2022 size = mdl->numPages * PAGE_SIZE;
2023 order = get_order(size);
2024 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2025 page = _GetNonPagedMemoryCache(Os, order);
2027 if (page == gcvNULL)
2030 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
2033 if (page == gcvNULL)
2035 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2038 vaddr = (gctPOINTER)page_address(page);
2039 mdl->contiguous = gcvTRUE;
2040 mdl->u.contiguousPages = page;
2041 addr = _CreateKernelVirtualMapping(mdl);
2042 mdl->dmaHandle = virt_to_phys(vaddr);
2044 mdl->u.contiguousPages = page;
2046 #if !defined(CONFIG_PPC)
2047 /* Cache invalidate. */
2048 dma_sync_single_for_device(
2057 SetPageReserved(virt_to_page(vaddr));
2064 if (addr == gcvNULL)
2066 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2071 /* Return allocated memory. */
2073 *Physical = (gctPHYS_ADDR) mdl;
2077 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
2079 if (mdlMap == gcvNULL)
2081 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2084 /* Only after mmap this will be valid. */
2086 /* We need to map this to user space. */
2087 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
2088 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
2090 mdl->numPages * PAGE_SIZE,
2091 PROT_READ | PROT_WRITE,
2095 down_write(¤t->mm->mmap_sem);
2097 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
2099 mdl->numPages * PAGE_SIZE,
2100 PROT_READ | PROT_WRITE,
2104 up_write(¤t->mm->mmap_sem);
2107 if (IS_ERR(mdlMap->vmaAddr))
2110 gcvLEVEL_WARNING, gcvZONE_OS,
2111 "%s(%d): do_mmap_pgoff error",
2112 __FUNCTION__, __LINE__
2115 mdlMap->vmaAddr = gcvNULL;
2117 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
2120 down_write(¤t->mm->mmap_sem);
2122 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
2124 if (mdlMap->vma == gcvNULL)
2127 gcvLEVEL_WARNING, gcvZONE_OS,
2128 "%s(%d): find_vma error",
2129 __FUNCTION__, __LINE__
2132 up_write(¤t->mm->mmap_sem);
2134 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2137 #ifndef NO_DMA_COHERENT
2138 if (dma_mmap_coherent(gcvNULL,
2142 mdl->numPages * PAGE_SIZE) < 0)
2145 gcvLEVEL_WARNING, gcvZONE_OS,
2146 "%s(%d): dma_mmap_coherent error",
2147 __FUNCTION__, __LINE__
2150 up_write(¤t->mm->mmap_sem);
2152 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2155 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
2156 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
2157 mdlMap->vma->vm_pgoff = 0;
2159 if (remap_pfn_range(mdlMap->vma,
2160 mdlMap->vma->vm_start,
2161 mdl->dmaHandle >> PAGE_SHIFT,
2162 mdl->numPages * PAGE_SIZE,
2163 mdlMap->vma->vm_page_prot))
2166 gcvLEVEL_WARNING, gcvZONE_OS,
2167 "%s(%d): remap_pfn_range error",
2168 __FUNCTION__, __LINE__
2171 up_write(¤t->mm->mmap_sem);
2173 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
2175 #endif /* NO_DMA_COHERENT */
2177 up_write(¤t->mm->mmap_sem);
2179 *Logical = mdlMap->vmaAddr;
2183 *Logical = (gctPOINTER)mdl->addr;
2187 * Add this to a global list.
2188 * Will be used by get physical address
2189 * and mapuser pointer functions.
2194 /* Initialize the queue. */
2195 Os->mdlHead = Os->mdlTail = mdl;
2199 /* Add to the tail. */
2200 mdl->prev = Os->mdlTail;
2201 Os->mdlTail->next = mdl;
2208 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
2209 *Bytes, *Physical, *Logical);
2210 return gcvSTATUS_OK;
2213 if (mdlMap != gcvNULL)
2215 /* Free LINUX_MDL_MAP. */
2216 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
2221 /* Free LINUX_MDL. */
2222 gcmkVERIFY_OK(_DestroyMdl(mdl));
2227 /* Unlock memory. */
2231 /* Return the status. */
2236 /*******************************************************************************
2238 ** gckOS_FreeNonPagedMemory
2240 ** Free previously allocated and mapped pages from non-paged memory.
2245 ** Pointer to an gckOS object.
2248 ** Number of bytes allocated.
2250 ** gctPHYS_ADDR Physical
2251 ** Physical address of the allocated memory.
2253 ** gctPOINTER Logical
2254 ** Logical address of the allocated memory.
2260 gceSTATUS gckOS_FreeNonPagedMemory(
2263 IN gctPHYS_ADDR Physical,
2264 IN gctPOINTER Logical
2268 PLINUX_MDL_MAP mdlMap;
2269 #ifdef NO_DMA_COHERENT
2272 #endif /* NO_DMA_COHERENT */
2274 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
2275 Os, Bytes, Physical, Logical);
2277 /* Verify the arguments. */
2278 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2279 gcmkVERIFY_ARGUMENT(Bytes > 0);
2280 gcmkVERIFY_ARGUMENT(Physical != 0);
2281 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2283 /* Convert physical address into a pointer to a MDL. */
2284 mdl = (PLINUX_MDL) Physical;
2288 #ifndef NO_DMA_COHERENT
2289 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2290 if (!_AddNonPagedMemoryCache(Os,
2291 mdl->numPages * PAGE_SIZE,
2296 dma_free_coherent(gcvNULL,
2297 mdl->numPages * PAGE_SIZE,
2302 size = mdl->numPages * PAGE_SIZE;
2307 ClearPageReserved(virt_to_page(vaddr));
2313 #if gcdUSE_NON_PAGED_MEMORY_CACHE
2314 if (!_AddNonPagedMemoryCache(Os,
2315 get_order(mdl->numPages * PAGE_SIZE),
2316 virt_to_page(mdl->kaddr)))
2319 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
2322 _DestoryKernelVirtualMapping(mdl->addr);
2323 #endif /* NO_DMA_COHERENT */
2327 while (mdlMap != gcvNULL)
2329 if (mdlMap->vmaAddr != gcvNULL)
2331 /* No mapped memory exists when free nonpaged memory */
2335 mdlMap = mdlMap->next;
2338 /* Remove the node from global list.. */
2339 if (mdl == Os->mdlHead)
2341 if ((Os->mdlHead = mdl->next) == gcvNULL)
2343 Os->mdlTail = gcvNULL;
2348 mdl->prev->next = mdl->next;
2349 if (mdl == Os->mdlTail)
2351 Os->mdlTail = mdl->prev;
2355 mdl->next->prev = mdl->prev;
2361 gcmkVERIFY_OK(_DestroyMdl(mdl));
2365 return gcvSTATUS_OK;
2368 /*******************************************************************************
2370 ** gckOS_ReadRegister
2372 ** Read data from a register.
2377 ** Pointer to an gckOS object.
2379 ** gctUINT32 Address
2380 ** Address of register.
2385 ** Pointer to a variable that receives the data read from the register.
2390 IN gctUINT32 Address,
2391 OUT gctUINT32 * Data
2394 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2398 gckOS_ReadRegisterEx(
2401 IN gctUINT32 Address,
2402 OUT gctUINT32 * Data
2405 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
2407 /* Verify the arguments. */
2408 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2409 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2410 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2412 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
2415 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2416 return gcvSTATUS_OK;
2419 /*******************************************************************************
2421 ** gckOS_WriteRegister
2423 ** Write data to a register.
2428 ** Pointer to an gckOS object.
2430 ** gctUINT32 Address
2431 ** Address of register.
2434 ** Data for register.
2441 gckOS_WriteRegister(
2443 IN gctUINT32 Address,
2447 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2451 gckOS_WriteRegisterEx(
2454 IN gctUINT32 Address,
2458 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2460 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2462 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2466 return gcvSTATUS_OK;
2469 /*******************************************************************************
2471 ** gckOS_GetPageSize
2473 ** Get the system's page size.
2478 ** Pointer to an gckOS object.
2482 ** gctSIZE_T * PageSize
2483 ** Pointer to a variable that will receive the system's page size.
2485 gceSTATUS gckOS_GetPageSize(
2487 OUT gctSIZE_T * PageSize
2490 gcmkHEADER_ARG("Os=0x%X", Os);
2492 /* Verify the arguments. */
2493 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2494 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2496 /* Return the page size. */
2497 *PageSize = (gctSIZE_T) PAGE_SIZE;
2500 gcmkFOOTER_ARG("*PageSize", *PageSize);
2501 return gcvSTATUS_OK;
2504 /*******************************************************************************
2506 ** gckOS_GetPhysicalAddress
2508 ** Get the physical system address of a corresponding virtual address.
2513 ** Pointer to an gckOS object.
2515 ** gctPOINTER Logical
2520 ** gctUINT32 * Address
2521 ** Poinetr to a variable that receives the 32-bit physical adress.
2524 gckOS_GetPhysicalAddress(
2526 IN gctPOINTER Logical,
2527 OUT gctUINT32 * Address
2531 gctUINT32 processID;
2533 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2535 /* Verify the arguments. */
2536 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2537 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2539 /* Query page table of current process first. */
2540 status = _QueryProcessPageTable(Logical, Address);
2542 if (gcmIS_ERROR(status))
2544 /* Get current process ID. */
2545 processID = _GetProcessID();
2547 /* Route through other function. */
2549 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2553 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2554 return gcvSTATUS_OK;
2557 /* Return the status. */
2566 IN gctUINT32 Physical,
2567 IN gctPOINTER Logical,
2572 gcsUSER_MAPPING_PTR map;
2574 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2575 Os, Physical, Logical, Bytes);
2577 gcmkONERROR(gckOS_Allocate(Os,
2578 gcmSIZEOF(gcsUSER_MAPPING),
2579 (gctPOINTER *) &map));
2581 map->next = Os->userMap;
2582 map->physical = Physical - Os->device->baseAddress;
2583 map->logical = Logical;
2585 map->start = (gctINT8_PTR) Logical;
2586 map->end = map->start + Bytes;
2591 return gcvSTATUS_OK;
2599 gckOS_RemoveMapping(
2601 IN gctPOINTER Logical,
2606 gcsUSER_MAPPING_PTR map, prev;
2608 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2610 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2612 if ((map->logical == Logical)
2613 && (map->bytes == Bytes)
2624 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2627 if (prev == gcvNULL)
2629 Os->userMap = map->next;
2633 prev->next = map->next;
2636 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2639 return gcvSTATUS_OK;
2648 _ConvertLogical2Physical(
2650 IN gctPOINTER Logical,
2651 IN gctUINT32 ProcessID,
2653 OUT gctUINT32_PTR Physical
2656 gctINT8_PTR base, vBase;
2659 gcsUSER_MAPPING_PTR userMap;
2661 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2663 /* Check for the logical address match. */
2664 if ((base != gcvNULL)
2665 && ((gctINT8_PTR) Logical >= base)
2666 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2669 offset = (gctINT8_PTR) Logical - base;
2671 if (Mdl->dmaHandle != 0)
2673 /* The memory was from coherent area. */
2674 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2676 else if (Mdl->pagedMem && !Mdl->contiguous)
2678 /* paged memory is not mapped to kernel space. */
2679 return gcvSTATUS_INVALID_ADDRESS;
2683 *Physical = gcmPTR2INT(virt_to_phys(base)) + offset;
2686 return gcvSTATUS_OK;
2689 /* Walk user maps. */
2690 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2692 if (((gctINT8_PTR) Logical >= userMap->start)
2693 && ((gctINT8_PTR) Logical < userMap->end)
2696 *Physical = userMap->physical
2697 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2699 return gcvSTATUS_OK;
2703 if (ProcessID != Os->kernelProcessID)
2705 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2706 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2708 /* Is the given address within that range. */
2709 if ((vBase != gcvNULL)
2710 && ((gctINT8_PTR) Logical >= vBase)
2711 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2714 offset = (gctINT8_PTR) Logical - vBase;
2716 if (Mdl->dmaHandle != 0)
2718 /* The memory was from coherent area. */
2719 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2721 else if (Mdl->pagedMem && !Mdl->contiguous)
2723 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2727 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2730 return gcvSTATUS_OK;
2734 /* Address not yet found. */
2735 return gcvSTATUS_INVALID_ADDRESS;
2738 /*******************************************************************************
2740 ** gckOS_GetPhysicalAddressProcess
2742 ** Get the physical system address of a corresponding virtual address for a
2748 ** Pointer to gckOS object.
2750 ** gctPOINTER Logical
2753 ** gctUINT32 ProcessID
2758 ** gctUINT32 * Address
2759 ** Poinetr to a variable that receives the 32-bit physical adress.
2762 gckOS_GetPhysicalAddressProcess(
2764 IN gctPOINTER Logical,
2765 IN gctUINT32 ProcessID,
2766 OUT gctUINT32 * Address
2771 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2773 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2775 /* Verify the arguments. */
2776 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2777 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2781 /* First try the contiguous memory pool. */
2782 if (Os->device->contiguousMapped)
2784 base = (gctINT8_PTR) Os->device->contiguousBase;
2786 if (((gctINT8_PTR) Logical >= base)
2787 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2790 /* Convert logical address into physical. */
2791 *Address = Os->device->contiguousVidMem->baseAddress
2792 + (gctINT8_PTR) Logical - base;
2793 status = gcvSTATUS_OK;
2798 /* Try the contiguous memory pool. */
2799 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2800 status = _ConvertLogical2Physical(Os,
2807 if (gcmIS_ERROR(status))
2809 /* Walk all MDLs. */
2810 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2813 status = _ConvertLogical2Physical(Os,
2818 if (gcmIS_SUCCESS(status))
2827 gcmkONERROR(status);
2830 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2831 return gcvSTATUS_OK;
2834 /* Return the status. */
2839 /*******************************************************************************
2841 ** gckOS_MapPhysical
2843 ** Map a physical address into kernel space.
2848 ** Pointer to an gckOS object.
2850 ** gctUINT32 Physical
2851 ** Physical address of the memory to map.
2854 ** Number of bytes to map.
2858 ** gctPOINTER * Logical
2859 ** Pointer to a variable that receives the base address of the mapped
2865 IN gctUINT32 Physical,
2867 OUT gctPOINTER * Logical
2872 gctUINT32 physical = Physical;
2874 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2876 /* Verify the arguments. */
2877 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2878 gcmkVERIFY_ARGUMENT(Bytes > 0);
2879 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2883 /* Go through our mapping to see if we know this physical address already. */
2886 while (mdl != gcvNULL)
2888 if (mdl->dmaHandle != 0)
2890 if ((physical >= mdl->dmaHandle)
2891 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2894 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2904 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
2905 struct contiguous_mem_pool *pool = Os->device->pool;
2907 if (Physical >= pool->phys && Physical < pool->phys + pool->size)
2908 logical = (gctPOINTER)(Physical - pool->phys + pool->virt);
2912 /* Map memory as cached memory. */
2913 request_mem_region(physical, Bytes, "MapRegion");
2914 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2917 if (logical == gcvNULL)
2920 gcvLEVEL_INFO, gcvZONE_OS,
2921 "%s(%d): Failed to map physical address 0x%08x",
2922 __FUNCTION__, __LINE__, Physical
2927 /* Out of resources. */
2928 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2929 return gcvSTATUS_OUT_OF_RESOURCES;
2932 /* Return pointer to mapped memory. */
2939 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2940 return gcvSTATUS_OK;
2943 /*******************************************************************************
2945 ** gckOS_UnmapPhysical
2947 ** Unmap a previously mapped memory region from kernel memory.
2952 ** Pointer to an gckOS object.
2954 ** gctPOINTER Logical
2955 ** Pointer to the base address of the memory to unmap.
2958 ** Number of bytes to unmap.
2965 gckOS_UnmapPhysical(
2967 IN gctPOINTER Logical,
2973 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2975 /* Verify the arguments. */
2976 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2977 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2978 gcmkVERIFY_ARGUMENT(Bytes > 0);
2984 while (mdl != gcvNULL)
2986 if (mdl->addr != gcvNULL)
2988 if (Logical >= (gctPOINTER)mdl->addr
2989 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
3000 /* Unmap the memory. */
3008 return gcvSTATUS_OK;
3011 /*******************************************************************************
3013 ** gckOS_CreateMutex
3015 ** Create a new mutex.
3020 ** Pointer to an gckOS object.
3024 ** gctPOINTER * Mutex
3025 ** Pointer to a variable that will hold a pointer to the mutex.
3030 OUT gctPOINTER * Mutex
3035 gcmkHEADER_ARG("Os=0x%X", Os);
3037 /* Validate the arguments. */
3038 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3039 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3041 /* Allocate the mutex structure. */
3042 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
3044 /* Initialize the mutex. */
3047 /* Return status. */
3048 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
3049 return gcvSTATUS_OK;
3052 /* Return status. */
3057 /*******************************************************************************
3059 ** gckOS_DeleteMutex
3066 ** Pointer to an gckOS object.
3069 ** Pointer to the mute to be deleted.
3083 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
3085 /* Validate the arguments. */
3086 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3087 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3089 /* Destroy the mutex. */
3090 mutex_destroy(Mutex);
3092 /* Free the mutex structure. */
3093 gcmkONERROR(gckOS_Free(Os, Mutex));
3096 return gcvSTATUS_OK;
3099 /* Return status. */
3104 /*******************************************************************************
3106 ** gckOS_AcquireMutex
3113 ** Pointer to an gckOS object.
3116 ** Pointer to the mutex to be acquired.
3118 ** gctUINT32 Timeout
3119 ** Timeout value specified in milliseconds.
3120 ** Specify the value of gcvINFINITE to keep the thread suspended
3121 ** until the mutex has been acquired.
3130 IN gctPOINTER Mutex,
3131 IN gctUINT32 Timeout
3134 #if gcdDETECT_TIMEOUT
3138 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
3140 /* Validate the arguments. */
3141 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3142 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3144 #if gcdDETECT_TIMEOUT
3149 /* Try to acquire the mutex. */
3150 if (mutex_trylock(Mutex))
3154 return gcvSTATUS_OK;
3157 /* Advance the timeout. */
3160 if (Timeout == gcvINFINITE)
3162 if (timeout == gcdINFINITE_TIMEOUT)
3164 gctUINT32 dmaAddress1, dmaAddress2;
3165 gctUINT32 dmaState1, dmaState2;
3167 dmaState1 = dmaState2 =
3168 dmaAddress1 = dmaAddress2 = 0;
3170 /* Verify whether DMA is running. */
3171 gcmkVERIFY_OK(_VerifyDMA(
3172 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
3175 #if gcdDETECT_DMA_ADDRESS
3176 /* Dump only if DMA appears stuck. */
3178 (dmaAddress1 == dmaAddress2)
3179 #if gcdDETECT_DMA_STATE
3180 && (dmaState1 == dmaState2)
3185 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
3188 "%s(%d): mutex 0x%X; forced message flush.",
3189 __FUNCTION__, __LINE__, Mutex
3192 /* Flush the debug cache. */
3193 gcmkDEBUGFLUSH(dmaAddress2);
3202 if (timeout >= Timeout)
3208 /* Wait for 1 millisecond. */
3209 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3212 if (Timeout == gcvINFINITE)
3214 /* Lock the mutex. */
3219 return gcvSTATUS_OK;
3224 /* Try to acquire the mutex. */
3225 if (mutex_trylock(Mutex))
3229 return gcvSTATUS_OK;
3237 /* Wait for 1 millisecond. */
3238 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
3243 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
3244 return gcvSTATUS_TIMEOUT;
3247 /*******************************************************************************
3249 ** gckOS_ReleaseMutex
3251 ** Release an acquired mutex.
3256 ** Pointer to an gckOS object.
3259 ** Pointer to the mutex to be released.
3271 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
3273 /* Validate the arguments. */
3274 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3275 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
3277 /* Release the mutex. */
3278 mutex_unlock(Mutex);
3282 return gcvSTATUS_OK;
3285 /*******************************************************************************
3287 ** gckOS_AtomicExchange
3289 ** Atomically exchange a pair of 32-bit values.
3294 ** Pointer to an gckOS object.
3296 ** IN OUT gctINT32_PTR Target
3297 ** Pointer to the 32-bit value to exchange.
3299 ** IN gctINT32 NewValue
3300 ** Specifies a new value for the 32-bit value pointed to by Target.
3302 ** OUT gctINT32_PTR OldValue
3303 ** The old value of the 32-bit value pointed to by Target.
3310 gckOS_AtomicExchange(
3312 IN OUT gctUINT32_PTR Target,
3313 IN gctUINT32 NewValue,
3314 OUT gctUINT32_PTR OldValue
3317 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
3319 /* Verify the arguments. */
3320 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3322 /* Exchange the pair of 32-bit values. */
3323 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
3326 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
3327 return gcvSTATUS_OK;
3330 /*******************************************************************************
3332 ** gckOS_AtomicExchangePtr
3334 ** Atomically exchange a pair of pointers.
3339 ** Pointer to an gckOS object.
3341 ** IN OUT gctPOINTER * Target
3342 ** Pointer to the 32-bit value to exchange.
3344 ** IN gctPOINTER NewValue
3345 ** Specifies a new value for the pointer pointed to by Target.
3347 ** OUT gctPOINTER * OldValue
3348 ** The old value of the pointer pointed to by Target.
3355 gckOS_AtomicExchangePtr(
3357 IN OUT gctPOINTER * Target,
3358 IN gctPOINTER NewValue,
3359 OUT gctPOINTER * OldValue
3362 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3364 /* Verify the arguments. */
3365 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3367 /* Exchange the pair of pointers. */
3368 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3371 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3372 return gcvSTATUS_OK;
3376 /*******************************************************************************
3378 ** gckOS_AtomicSetMask
3380 ** Atomically set mask to Atom
3383 ** IN OUT gctPOINTER Atom
3384 ** Pointer to the atom to set.
3386 ** IN gctUINT32 Mask
3399 gctUINT32 oval, nval;
3401 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3402 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3406 oval = atomic_read((atomic_t *) Atom);
3408 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3411 return gcvSTATUS_OK;
3414 /*******************************************************************************
3416 ** gckOS_AtomClearMask
3418 ** Atomically clear mask from Atom
3421 ** IN OUT gctPOINTER Atom
3422 ** Pointer to the atom to clear.
3424 ** IN gctUINT32 Mask
3432 gckOS_AtomClearMask(
3437 gctUINT32 oval, nval;
3439 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3440 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3444 oval = atomic_read((atomic_t *) Atom);
3445 nval = oval & ~Mask;
3446 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3449 return gcvSTATUS_OK;
3453 /*******************************************************************************
3455 ** gckOS_AtomConstruct
3462 ** Pointer to a gckOS object.
3466 ** gctPOINTER * Atom
3467 ** Pointer to a variable receiving the constructed atom.
3470 gckOS_AtomConstruct(
3472 OUT gctPOINTER * Atom
3477 gcmkHEADER_ARG("Os=0x%X", Os);
3479 /* Verify the arguments. */
3480 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3481 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3483 /* Allocate the atom. */
3484 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3486 /* Initialize the atom. */
3487 atomic_set((atomic_t *) *Atom, 0);
3490 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3491 return gcvSTATUS_OK;
3494 /* Return the status. */
3499 /*******************************************************************************
3501 ** gckOS_AtomDestroy
3508 ** Pointer to a gckOS object.
3511 ** Pointer to the atom to destroy.
3525 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3527 /* Verify the arguments. */
3528 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3529 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3531 /* Free the atom. */
3532 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3536 return gcvSTATUS_OK;
3539 /* Return the status. */
3544 /*******************************************************************************
3548 ** Get the 32-bit value protected by an atom.
3553 ** Pointer to a gckOS object.
3556 ** Pointer to the atom.
3560 ** gctINT32_PTR Value
3561 ** Pointer to a variable the receives the value of the atom.
3567 OUT gctINT32_PTR Value
3570 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3572 /* Verify the arguments. */
3573 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3574 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3576 /* Return the current value of atom. */
3577 *Value = atomic_read((atomic_t *) Atom);
3580 gcmkFOOTER_ARG("*Value=%d", *Value);
3581 return gcvSTATUS_OK;
3584 /*******************************************************************************
3588 ** Set the 32-bit value protected by an atom.
3593 ** Pointer to a gckOS object.
3596 ** Pointer to the atom.
3599 ** The value of the atom.
3612 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3614 /* Verify the arguments. */
3615 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3616 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3618 /* Set the current value of atom. */
3619 atomic_set((atomic_t *) Atom, Value);
3623 return gcvSTATUS_OK;
3626 /*******************************************************************************
3628 ** gckOS_AtomIncrement
3630 ** Atomically increment the 32-bit integer value inside an atom.
3635 ** Pointer to a gckOS object.
3638 ** Pointer to the atom.
3642 ** gctINT32_PTR Value
3643 ** Pointer to a variable that receives the original value of the atom.
3646 gckOS_AtomIncrement(
3649 OUT gctINT32_PTR Value
3652 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3654 /* Verify the arguments. */
3655 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3656 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3658 /* Increment the atom. */
3659 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3662 gcmkFOOTER_ARG("*Value=%d", *Value);
3663 return gcvSTATUS_OK;
3666 /*******************************************************************************
3668 ** gckOS_AtomDecrement
3670 ** Atomically decrement the 32-bit integer value inside an atom.
3675 ** Pointer to a gckOS object.
3678 ** Pointer to the atom.
3682 ** gctINT32_PTR Value
3683 ** Pointer to a variable that receives the original value of the atom.
3686 gckOS_AtomDecrement(
3689 OUT gctINT32_PTR Value
3692 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3694 /* Verify the arguments. */
3695 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3696 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3698 /* Decrement the atom. */
3699 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3702 gcmkFOOTER_ARG("*Value=%d", *Value);
3703 return gcvSTATUS_OK;
3706 /*******************************************************************************
3710 ** Delay execution of the current thread for a number of milliseconds.
3715 ** Pointer to an gckOS object.
3718 ** Delay to sleep, specified in milliseconds.
3730 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3734 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3735 ktime_t delay = ktime_set(Delay/1000, (Delay%1000) * NSEC_PER_MSEC);
3736 __set_current_state(TASK_UNINTERRUPTIBLE);
3737 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3746 return gcvSTATUS_OK;
3749 /*******************************************************************************
3753 ** Get the number of milliseconds since the system started.
3759 ** gctUINT32_PTR Time
3760 ** Pointer to a variable to get time.
3765 OUT gctUINT32_PTR Time
3770 *Time = jiffies_to_msecs(jiffies);
3773 return gcvSTATUS_OK;
3776 /*******************************************************************************
3780 ** Compare time values got from gckOS_GetTicks.
3784 ** First time value to be compared.
3787 ** Second time value to be compared.
3791 ** gctBOOL_PTR IsAfter
3792 ** Pointer to a variable to result.
3799 OUT gctBOOL_PTR IsAfter
3804 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3807 return gcvSTATUS_OK;
3810 /*******************************************************************************
3814 ** Get the number of microseconds since the system started.
3820 ** gctUINT64_PTR Time
3821 ** Pointer to a variable to get time.
3826 OUT gctUINT64_PTR Time
3834 return gcvSTATUS_OK;
3837 /*******************************************************************************
3839 ** gckOS_MemoryBarrier
3841 ** Make sure the CPU has executed everything up to this point and the data got
3842 ** written to the specified pointer.
3847 ** Pointer to an gckOS object.
3849 ** gctPOINTER Address
3850 ** Address of memory that needs to be barriered.
3857 gckOS_MemoryBarrier(
3859 IN gctPOINTER Address
3862 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3864 /* Verify the arguments. */
3865 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3867 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3868 && defined (CONFIG_ARM) \
3869 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3870 /* drain write buffer */
3873 /* drain outer cache's write buffer? */
3880 return gcvSTATUS_OK;
3883 /*******************************************************************************
3885 ** gckOS_AllocatePagedMemory
3887 ** Allocate memory from the paged pool.
3892 ** Pointer to an gckOS object.
3895 ** Number of bytes to allocate.
3899 ** gctPHYS_ADDR * Physical
3900 ** Pointer to a variable that receives the physical address of the
3901 ** memory allocation.
3904 gckOS_AllocatePagedMemory(
3907 OUT gctPHYS_ADDR * Physical
3912 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3914 /* Verify the arguments. */
3915 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3916 gcmkVERIFY_ARGUMENT(Bytes > 0);
3917 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3919 /* Allocate the memory. */
3920 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical));
3923 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3924 return gcvSTATUS_OK;
3927 /* Return the status. */
3932 /*******************************************************************************
3934 ** gckOS_AllocatePagedMemoryEx
3936 ** Allocate memory from the paged pool.
3941 ** Pointer to an gckOS object.
3943 ** gctBOOL Contiguous
3944 ** Need contiguous memory or not.
3947 ** Number of bytes to allocate.
3951 ** gctPHYS_ADDR * Physical
3952 ** Pointer to a variable that receives the physical address of the
3953 ** memory allocation.
3956 gckOS_AllocatePagedMemoryEx(
3958 IN gctBOOL Contiguous,
3960 OUT gctPHYS_ADDR * Physical
3965 PLINUX_MDL mdl = gcvNULL;
3967 gctBOOL locked = gcvFALSE;
3969 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
3970 gctPOINTER addr = gcvNULL;
3973 gcmkHEADER_ARG("Os=0x%X Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
3975 /* Verify the arguments. */
3976 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3977 gcmkVERIFY_ARGUMENT(Bytes > 0);
3978 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3980 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3982 numPages = GetPageCount(bytes, 0);
3987 mdl = _CreateMdl(_GetProcessID());
3990 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3995 gctUINT32 order = get_order(bytes);
3997 if (order >= MAX_ORDER)
3999 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4002 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4004 alloc_pages_exact(numPages * PAGE_SIZE, GFP_KERNEL | gcdNOWARN | __GFP_NORETRY);
4006 mdl->u.contiguousPages = addr
4007 ? virt_to_page(addr)
4010 mdl->exact = gcvTRUE;
4012 mdl->u.contiguousPages =
4013 alloc_pages(GFP_KERNEL | gcdNOWARN | __GFP_NORETRY, order);
4015 if (mdl->u.contiguousPages == gcvNULL)
4017 mdl->u.contiguousPages =
4018 alloc_pages(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN, order);
4020 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4021 mdl->exact = gcvFALSE;
4027 mdl->u.nonContiguousPages = _NonContiguousAlloc(numPages);
4030 if (mdl->u.contiguousPages == gcvNULL && mdl->u.nonContiguousPages == gcvNULL)
4032 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4037 mdl->numPages = numPages;
4039 mdl->contiguous = Contiguous;
4041 for (i = 0; i < mdl->numPages; i++)
4045 if (mdl->contiguous)
4047 page = nth_page(mdl->u.contiguousPages, i);
4051 page = _NonContiguousToPage(mdl->u.nonContiguousPages, i);
4054 SetPageReserved(page);
4056 if (!PageHighMem(page) && page_to_phys(page))
4059 gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
4060 (gctPOINTER)(gctUINTPTR_T)page_to_phys(page),
4066 /* Return physical address. */
4067 *Physical = (gctPHYS_ADDR) mdl;
4070 * Add this to a global list.
4071 * Will be used by get physical address
4072 * and mapuser pointer functions.
4076 /* Initialize the queue. */
4077 Os->mdlHead = Os->mdlTail = mdl;
4082 mdl->prev = Os->mdlTail;
4083 Os->mdlTail->next = mdl;
4090 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
4091 return gcvSTATUS_OK;
4096 /* Free the memory. */
4102 /* Unlock the memory. */
4106 /* Return the status. */
4111 /*******************************************************************************
4113 ** gckOS_FreePagedMemory
4115 ** Free memory allocated from the paged pool.
4120 ** Pointer to an gckOS object.
4122 ** gctPHYS_ADDR Physical
4123 ** Physical address of the allocation.
4126 ** Number of bytes of the allocation.
4133 gckOS_FreePagedMemory(
4135 IN gctPHYS_ADDR Physical,
4139 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
4142 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
4144 /* Verify the arguments. */
4145 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4146 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4147 gcmkVERIFY_ARGUMENT(Bytes > 0);
4149 /*addr = mdl->addr;*/
4153 for (i = 0; i < mdl->numPages; i++)
4155 if (mdl->contiguous)
4157 ClearPageReserved(nth_page(mdl->u.contiguousPages, i));
4161 ClearPageReserved(_NonContiguousToPage(mdl->u.nonContiguousPages, i));
4165 if (mdl->contiguous)
4167 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
4168 if (mdl->exact == gcvTRUE)
4170 free_pages_exact(page_address(mdl->u.contiguousPages), mdl->numPages * PAGE_SIZE);
4175 __free_pages(mdl->u.contiguousPages, GetOrder(mdl->numPages));
4180 _NonContiguousFree(mdl->u.nonContiguousPages, mdl->numPages);
4183 /* Remove the node from global list. */
4184 if (mdl == Os->mdlHead)
4186 if ((Os->mdlHead = mdl->next) == gcvNULL)
4188 Os->mdlTail = gcvNULL;
4193 mdl->prev->next = mdl->next;
4195 if (mdl == Os->mdlTail)
4197 Os->mdlTail = mdl->prev;
4201 mdl->next->prev = mdl->prev;
4207 /* Free the structure... */
4208 gcmkVERIFY_OK(_DestroyMdl(mdl));
4212 return gcvSTATUS_OK;
4215 /*******************************************************************************
4219 ** Lock memory allocated from the paged pool.
4224 ** Pointer to an gckOS object.
4226 ** gctPHYS_ADDR Physical
4227 ** Physical address of the allocation.
4230 ** Number of bytes of the allocation.
4232 ** gctBOOL Cacheable
4233 ** Cache mode of mapping.
4237 ** gctPOINTER * Logical
4238 ** Pointer to a variable that receives the address of the mapped
4241 ** gctSIZE_T * PageCount
4242 ** Pointer to a variable that receives the number of pages required for
4243 ** the page table according to the GPU page size.
4248 IN gctPHYS_ADDR Physical,
4250 IN gctBOOL Cacheable,
4251 OUT gctPOINTER * Logical,
4252 OUT gctSIZE_T * PageCount
4256 PLINUX_MDL_MAP mdlMap;
4258 unsigned long start;
4262 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
4264 /* Verify the arguments. */
4265 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4266 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4267 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4268 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
4270 mdl = (PLINUX_MDL) Physical;
4274 mdlMap = FindMdlMap(mdl, _GetProcessID());
4276 if (mdlMap == gcvNULL)
4278 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
4280 if (mdlMap == gcvNULL)
4284 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4285 return gcvSTATUS_OUT_OF_MEMORY;
4289 if (mdlMap->vmaAddr == gcvNULL)
4291 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
4292 mdlMap->vmaAddr = (gctSTRING)vm_mmap(gcvNULL,
4294 mdl->numPages * PAGE_SIZE,
4295 PROT_READ | PROT_WRITE,
4299 down_write(¤t->mm->mmap_sem);
4301 mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
4303 mdl->numPages * PAGE_SIZE,
4304 PROT_READ | PROT_WRITE,
4308 up_write(¤t->mm->mmap_sem);
4312 gcvLEVEL_INFO, gcvZONE_OS,
4313 "%s(%d): vmaAddr->0x%X for phys_addr->0x%X",
4314 __FUNCTION__, __LINE__,
4315 (gctUINT32)(gctUINTPTR_T)mdlMap->vmaAddr,
4316 (gctUINT32)(gctUINTPTR_T)mdl
4319 if (IS_ERR(mdlMap->vmaAddr))
4322 gcvLEVEL_INFO, gcvZONE_OS,
4323 "%s(%d): do_mmap_pgoff error",
4324 __FUNCTION__, __LINE__
4327 mdlMap->vmaAddr = gcvNULL;
4331 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4332 return gcvSTATUS_OUT_OF_MEMORY;
4335 down_write(¤t->mm->mmap_sem);
4337 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
4339 if (mdlMap->vma == gcvNULL)
4341 up_write(¤t->mm->mmap_sem);
4344 gcvLEVEL_INFO, gcvZONE_OS,
4345 "%s(%d): find_vma error",
4346 __FUNCTION__, __LINE__
4349 mdlMap->vmaAddr = gcvNULL;
4353 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_RESOURCES);
4354 return gcvSTATUS_OUT_OF_RESOURCES;
4357 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
4359 if (Cacheable == gcvFALSE)
4361 /* Make this mapping non-cached. */
4362 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
4367 /* Now map all the vmalloc pages to this user address. */
4368 if (mdl->contiguous)
4370 /* map kernel memory to user space.. */
4371 if (remap_pfn_range(mdlMap->vma,
4372 mdlMap->vma->vm_start,
4373 page_to_pfn(mdl->u.contiguousPages),
4374 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
4375 mdlMap->vma->vm_page_prot) < 0)
4377 up_write(¤t->mm->mmap_sem);
4380 gcvLEVEL_INFO, gcvZONE_OS,
4381 "%s(%d): unable to mmap ret",
4382 __FUNCTION__, __LINE__
4385 mdlMap->vmaAddr = gcvNULL;
4389 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4390 return gcvSTATUS_OUT_OF_MEMORY;
4395 start = mdlMap->vma->vm_start;
4397 for (i = 0; i < mdl->numPages; i++)
4399 pfn = _NonContiguousToPfn(mdl->u.nonContiguousPages, i);
4401 if (remap_pfn_range(mdlMap->vma,
4405 mdlMap->vma->vm_page_prot) < 0)
4407 up_write(¤t->mm->mmap_sem);
4410 gcvLEVEL_INFO, gcvZONE_OS,
4411 "%s(%d): gctPHYS_ADDR->0x%X Logical->0x%X Unable to map addr->0x%X to start->0x%X",
4412 __FUNCTION__, __LINE__,
4413 (gctUINT32)(gctUINTPTR_T)Physical,
4414 (gctUINT32)(gctUINTPTR_T)*Logical,
4415 (gctUINT32)(gctUINTPTR_T)addr,
4416 (gctUINT32)(gctUINTPTR_T)start
4419 mdlMap->vmaAddr = gcvNULL;
4423 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4424 return gcvSTATUS_OUT_OF_MEMORY;
4432 up_write(¤t->mm->mmap_sem);
4436 /* mdlMap->vmaAddr != gcvNULL means current process has already locked this node. */
4439 gcmkFOOTER_ARG("*status=%d, mdlMap->vmaAddr=%x", gcvSTATUS_MEMORY_LOCKED, mdlMap->vmaAddr);
4440 return gcvSTATUS_MEMORY_LOCKED;
4443 /* Convert pointer to MDL. */
4444 *Logical = mdlMap->vmaAddr;
4446 /* Return the page number according to the GPU page size. */
4447 gcmkASSERT((PAGE_SIZE % 4096) == 0);
4448 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
4450 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
4454 gcmkVERIFY_OK(gckOS_CacheFlush(
4459 (gctPOINTER)mdlMap->vmaAddr,
4460 mdl->numPages * PAGE_SIZE
4464 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
4465 return gcvSTATUS_OK;
4468 /*******************************************************************************
4472 ** Map paged memory into a page table.
4477 ** Pointer to an gckOS object.
4479 ** gctPHYS_ADDR Physical
4480 ** Physical address of the allocation.
4482 ** gctSIZE_T PageCount
4483 ** Number of pages required for the physical address.
4485 ** gctPOINTER PageTable
4486 ** Pointer to the page table to fill in.
4495 IN gctPHYS_ADDR Physical,
4496 IN gctSIZE_T PageCount,
4497 IN gctPOINTER PageTable
4500 return gckOS_MapPagesEx(Os,
4511 IN gctPHYS_ADDR Physical,
4512 IN gctSIZE_T PageCount,
4513 IN gctPOINTER PageTable
4516 gceSTATUS status = gcvSTATUS_OK;
4520 #if gcdNONPAGED_MEMORY_CACHEABLE
4524 gctPHYS_ADDR pageTablePhysical;
4527 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
4528 Os, Core, Physical, PageCount, PageTable);
4530 /* Verify the arguments. */
4531 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4532 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4533 gcmkVERIFY_ARGUMENT(PageCount > 0);
4534 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
4536 /* Convert pointer to MDL. */
4537 mdl = (PLINUX_MDL)Physical;
4540 gcvLEVEL_INFO, gcvZONE_OS,
4541 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4542 __FUNCTION__, __LINE__,
4543 (gctUINT32)(gctUINTPTR_T)Physical,
4544 (gctUINT32)(gctUINTPTR_T)PageCount,
4550 table = (gctUINT32 *)PageTable;
4551 #if gcdNONPAGED_MEMORY_CACHEABLE
4552 mmu = Os->device->kernels[Core]->mmu;
4553 bytes = PageCount * sizeof(*table);
4554 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4557 /* Get all the physical addresses and store them in the page table. */
4563 /* Try to get the user pages so DMA can happen. */
4564 while (PageCount-- > 0)
4567 if (Core == gcvCORE_VG)
4569 if (mdl->contiguous)
4572 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4573 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4579 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4580 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4587 if (mdl->contiguous)
4590 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4591 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4597 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4598 _NonContiguousToPhys(mdl->u.nonContiguousPages, offset),
4610 gcvLEVEL_INFO, gcvZONE_OS,
4611 "%s(%d): we should not get this call for Non Paged Memory!",
4612 __FUNCTION__, __LINE__
4615 while (PageCount-- > 0)
4618 if (Core == gcvCORE_VG)
4621 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4622 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4629 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4630 page_to_phys(nth_page(mdl->u.contiguousPages, offset)),
4638 #if gcdNONPAGED_MEMORY_CACHEABLE
4639 /* Get physical address of pageTable */
4640 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4641 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4643 /* Flush the mmu page table cache. */
4644 gcmkONERROR(gckOS_CacheClean(
4658 /* Return the status. */
4663 /*******************************************************************************
4665 ** gckOS_UnlockPages
4667 ** Unlock memory allocated from the paged pool.
4672 ** Pointer to an gckOS object.
4674 ** gctPHYS_ADDR Physical
4675 ** Physical address of the allocation.
4678 ** Number of bytes of the allocation.
4680 ** gctPOINTER Logical
4681 ** Address of the mapped memory.
4690 IN gctPHYS_ADDR Physical,
4692 IN gctPOINTER Logical
4695 PLINUX_MDL_MAP mdlMap;
4696 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4698 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4699 Os, Physical, Bytes, Logical);
4701 /* Verify the arguments. */
4702 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4703 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4704 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4706 /* Make sure there is already a mapping...*/
4707 gcmkVERIFY_ARGUMENT(mdl->u.nonContiguousPages != gcvNULL
4708 || mdl->u.contiguousPages != gcvNULL);
4714 while (mdlMap != gcvNULL)
4716 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4718 _UnmapUserLogical(mdlMap->pid, mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
4719 mdlMap->vmaAddr = gcvNULL;
4722 mdlMap = mdlMap->next;
4729 return gcvSTATUS_OK;
4733 /*******************************************************************************
4735 ** gckOS_AllocateContiguous
4737 ** Allocate memory from the contiguous pool.
4742 ** Pointer to an gckOS object.
4744 ** gctBOOL InUserSpace
4745 ** gcvTRUE if the pages need to be mapped into user space.
4747 ** gctSIZE_T * Bytes
4748 ** Pointer to the number of bytes to allocate.
4752 ** gctSIZE_T * Bytes
4753 ** Pointer to a variable that receives the number of bytes allocated.
4755 ** gctPHYS_ADDR * Physical
4756 ** Pointer to a variable that receives the physical address of the
4757 ** memory allocation.
4759 ** gctPOINTER * Logical
4760 ** Pointer to a variable that receives the logical address of the
4761 ** memory allocation.
4764 gckOS_AllocateContiguous(
4766 IN gctBOOL InUserSpace,
4767 IN OUT gctSIZE_T * Bytes,
4768 OUT gctPHYS_ADDR * Physical,
4769 OUT gctPOINTER * Logical
4774 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4775 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4777 /* Verify the arguments. */
4778 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4779 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4780 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4781 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4782 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4784 /* Same as non-paged memory for now. */
4785 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4792 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4793 *Bytes, *Physical, *Logical);
4794 return gcvSTATUS_OK;
4797 /* Return the status. */
4802 /*******************************************************************************
4804 ** gckOS_FreeContiguous
4806 ** Free memory allocated from the contiguous pool.
4811 ** Pointer to an gckOS object.
4813 ** gctPHYS_ADDR Physical
4814 ** Physical address of the allocation.
4816 ** gctPOINTER Logical
4817 ** Logicval address of the allocation.
4820 ** Number of bytes of the allocation.
4827 gckOS_FreeContiguous(
4829 IN gctPHYS_ADDR Physical,
4830 IN gctPOINTER Logical,
4836 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4837 Os, Physical, Logical, Bytes);
4839 /* Verify the arguments. */
4840 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4841 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4842 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4843 gcmkVERIFY_ARGUMENT(Bytes > 0);
4845 /* Same of non-paged memory for now. */
4846 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4850 return gcvSTATUS_OK;
4853 /* Return the status. */
4859 /******************************************************************************
4861 ** gckOS_GetKernelLogical
4863 ** Return the kernel logical pointer that corresponods to the specified
4864 ** hardware address.
4869 ** Pointer to an gckOS object.
4871 ** gctUINT32 Address
4872 ** Hardware physical address.
4876 ** gctPOINTER * KernelPointer
4877 ** Pointer to a variable receiving the pointer in kernel address space.
4880 gckOS_GetKernelLogical(
4882 IN gctUINT32 Address,
4883 OUT gctPOINTER * KernelPointer
4886 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4890 gckOS_GetKernelLogicalEx(
4893 IN gctUINT32 Address,
4894 OUT gctPOINTER * KernelPointer
4899 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4903 gckGALDEVICE device;
4909 /* Extract the pointer to the gckGALDEVICE class. */
4910 device = (gckGALDEVICE) Os->device;
4912 /* Kernel shortcut. */
4913 kernel = device->kernels[Core];
4915 if (Core == gcvCORE_VG)
4917 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4918 kernel->vg->hardware, Address, &pool, &offset
4924 /* Split the memory address into a pool type and offset. */
4925 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4926 kernel->hardware, Address, &pool, &offset
4930 /* Dispatch on pool. */
4933 case gcvPOOL_LOCAL_INTERNAL:
4934 /* Internal memory. */
4935 logical = device->internalLogical;
4938 case gcvPOOL_LOCAL_EXTERNAL:
4939 /* External memory. */
4940 logical = device->externalLogical;
4943 case gcvPOOL_SYSTEM:
4944 /* System memory. */
4945 logical = device->contiguousBase;
4949 /* Invalid memory pool. */
4951 return gcvSTATUS_INVALID_ARGUMENT;
4954 /* Build logical address of specified address. */
4955 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4958 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4959 return gcvSTATUS_OK;
4963 /* Return status. */
4969 /*******************************************************************************
4971 ** gckOS_MapUserPointer
4973 ** Map a pointer from the user process into the kernel address space.
4978 ** Pointer to an gckOS object.
4980 ** gctPOINTER Pointer
4981 ** Pointer in user process space that needs to be mapped.
4984 ** Number of bytes that need to be mapped.
4988 ** gctPOINTER * KernelPointer
4989 ** Pointer to a variable receiving the mapped pointer in kernel address
4993 gckOS_MapUserPointer(
4995 IN gctPOINTER Pointer,
4997 OUT gctPOINTER * KernelPointer
5000 gctPOINTER buf = gcvNULL;
5003 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
5005 /* Verify the arguments. */
5006 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5007 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5008 gcmkVERIFY_ARGUMENT(Size > 0);
5009 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5011 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
5016 "%s(%d): Failed to allocate memory.",
5017 __FUNCTION__, __LINE__
5020 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
5021 return gcvSTATUS_OUT_OF_MEMORY;
5024 len = copy_from_user(buf, Pointer, Size);
5029 "%s(%d): Failed to copy data from user.",
5030 __FUNCTION__, __LINE__
5038 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
5039 return gcvSTATUS_GENERIC_IO;
5042 *KernelPointer = buf;
5044 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
5045 return gcvSTATUS_OK;
5048 /*******************************************************************************
5050 ** gckOS_UnmapUserPointer
5052 ** Unmap a user process pointer from the kernel address space.
5057 ** Pointer to an gckOS object.
5059 ** gctPOINTER Pointer
5060 ** Pointer in user process space that needs to be unmapped.
5063 ** Number of bytes that need to be unmapped.
5065 ** gctPOINTER KernelPointer
5066 ** Pointer in kernel address space that needs to be unmapped.
5073 gckOS_UnmapUserPointer(
5075 IN gctPOINTER Pointer,
5077 IN gctPOINTER KernelPointer
5082 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
5083 Os, Pointer, Size, KernelPointer);
5086 /* Verify the arguments. */
5087 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5088 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5089 gcmkVERIFY_ARGUMENT(Size > 0);
5090 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5092 len = copy_to_user(Pointer, KernelPointer, Size);
5094 kfree(KernelPointer);
5100 "%s(%d): Failed to copy data to user.",
5101 __FUNCTION__, __LINE__
5104 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
5105 return gcvSTATUS_GENERIC_IO;
5109 return gcvSTATUS_OK;
5112 /*******************************************************************************
5114 ** gckOS_QueryNeedCopy
5116 ** Query whether the memory can be accessed or mapped directly or it has to be
5122 ** Pointer to an gckOS object.
5124 ** gctUINT32 ProcessID
5125 ** Process ID of the current process.
5129 ** gctBOOL_PTR NeedCopy
5130 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
5131 ** gcvFALSE if the memory can be accessed or mapped dircetly.
5134 gckOS_QueryNeedCopy(
5136 IN gctUINT32 ProcessID,
5137 OUT gctBOOL_PTR NeedCopy
5140 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
5142 /* Verify the arguments. */
5143 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5144 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
5146 /* We need to copy data. */
5147 *NeedCopy = gcvTRUE;
5150 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
5151 return gcvSTATUS_OK;
5154 /*******************************************************************************
5156 ** gckOS_CopyFromUserData
5158 ** Copy data from user to kernel memory.
5163 ** Pointer to an gckOS object.
5165 ** gctPOINTER KernelPointer
5166 ** Pointer to kernel memory.
5168 ** gctPOINTER Pointer
5169 ** Pointer to user memory.
5172 ** Number of bytes to copy.
5179 gckOS_CopyFromUserData(
5181 IN gctPOINTER KernelPointer,
5182 IN gctPOINTER Pointer,
5188 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5189 Os, KernelPointer, Pointer, Size);
5191 /* Verify the arguments. */
5192 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5193 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5194 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5195 gcmkVERIFY_ARGUMENT(Size > 0);
5197 /* Copy data from user. */
5198 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
5200 /* Could not copy all the bytes. */
5201 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5206 return gcvSTATUS_OK;
5209 /* Return the status. */
5214 /*******************************************************************************
5216 ** gckOS_CopyToUserData
5218 ** Copy data from kernel to user memory.
5223 ** Pointer to an gckOS object.
5225 ** gctPOINTER KernelPointer
5226 ** Pointer to kernel memory.
5228 ** gctPOINTER Pointer
5229 ** Pointer to user memory.
5232 ** Number of bytes to copy.
5239 gckOS_CopyToUserData(
5241 IN gctPOINTER KernelPointer,
5242 IN gctPOINTER Pointer,
5248 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
5249 Os, KernelPointer, Pointer, Size);
5251 /* Verify the arguments. */
5252 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5253 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
5254 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
5255 gcmkVERIFY_ARGUMENT(Size > 0);
5257 /* Copy data to user. */
5258 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
5260 /* Could not copy all the bytes. */
5261 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5266 return gcvSTATUS_OK;
5269 /* Return the status. */
5274 /*******************************************************************************
5276 ** gckOS_WriteMemory
5278 ** Write data to a memory.
5283 ** Pointer to an gckOS object.
5285 ** gctPOINTER Address
5286 ** Address of the memory to write to.
5289 ** Data for register.
5298 IN gctPOINTER Address,
5303 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
5305 /* Verify the arguments. */
5306 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5309 if (access_ok(VERIFY_WRITE, Address, 4))
5312 if(put_user(Data, (gctUINT32*)Address))
5314 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
5319 /* Kernel address. */
5320 *(gctUINT32 *)Address = Data;
5325 return gcvSTATUS_OK;
5332 /*******************************************************************************
5334 ** gckOS_MapUserMemory
5336 ** Lock down a user buffer and return an DMA'able address to be used by the
5337 ** hardware to access it.
5341 ** gctPOINTER Memory
5342 ** Pointer to memory to lock down.
5345 ** Size in bytes of the memory to lock down.
5349 ** gctPOINTER * Info
5350 ** Pointer to variable receiving the information record required by
5351 ** gckOS_UnmapUserMemory.
5353 ** gctUINT32_PTR Address
5354 ** Pointer to a variable that will receive the address DMA'able by the
5358 gckOS_MapUserMemory(
5361 IN gctPOINTER Memory,
5362 IN gctUINT32 Physical,
5364 OUT gctPOINTER * Info,
5365 OUT gctUINT32_PTR Address
5370 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
5373 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
5376 return gcvSTATUS_OK;
5383 gctSIZE_T pageCount, i, j;
5384 gctUINT32_PTR pageTable;
5385 gctUINT32 address = 0, physical = ~0U;
5386 gctUINTPTR_T start, end, memory;
5390 gcsPageInfo_PTR info = gcvNULL;
5391 struct page **pages = gcvNULL;
5393 /* Verify the arguments. */
5394 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5395 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
5396 gcmkVERIFY_ARGUMENT(Size > 0);
5397 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5398 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
5402 memory = (gctUINTPTR_T) Memory;
5404 /* Get the number of required pages. */
5405 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5406 start = memory >> PAGE_SHIFT;
5407 pageCount = end - start;
5410 gcvLEVEL_INFO, gcvZONE_OS,
5411 "%s(%d): pageCount: %d.",
5412 __FUNCTION__, __LINE__,
5417 if ((memory + Size) < memory)
5419 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5420 return gcvSTATUS_INVALID_ARGUMENT;
5423 MEMORY_MAP_LOCK(Os);
5425 /* Allocate the Info struct. */
5426 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
5428 if (info == gcvNULL)
5430 status = gcvSTATUS_OUT_OF_MEMORY;
5434 /* Allocate the array of page addresses. */
5435 pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
5437 if (pages == gcvNULL)
5439 status = gcvSTATUS_OUT_OF_MEMORY;
5443 if (Physical != ~0U)
5445 for (i = 0; i < pageCount; i++)
5447 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
5453 /* Get the user pages. */
5454 down_read(¤t->mm->mmap_sem);
5456 result = get_user_pages(current,
5466 up_read(¤t->mm->mmap_sem);
5468 if (result <=0 || result < pageCount)
5470 struct vm_area_struct *vma;
5472 /* Release the pages if any. */
5475 for (i = 0; i < result; i++)
5477 if (pages[i] == gcvNULL)
5482 page_cache_release(pages[i]);
5489 vma = find_vma(current->mm, memory);
5491 if (vma && (vma->vm_flags & VM_PFNMAP))
5495 gctUINTPTR_T logical = memory;
5497 for (i = 0; i < pageCount; i++)
5499 pgd_t * pgd = pgd_offset(current->mm, logical);
5500 pud_t * pud = pud_offset(pgd, logical);
5504 pmd_t * pmd = pmd_offset(pud, logical);
5505 pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
5508 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5513 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5516 pages[i] = pte_page(*pte);
5517 pte_unmap_unlock(pte, ptl);
5519 /* Advance to next. */
5520 logical += PAGE_SIZE;
5525 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5528 /* Check if this memory is contiguous for old mmu. */
5529 if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
5531 for (i = 1; i < pageCount; i++)
5533 if (pages[i] != nth_page(pages[0], i))
5535 /* Non-contiguous. */
5542 /* Contiguous memory. */
5543 physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
5545 if (!((physical - Os->device->baseAddress) & 0x80000000))
5550 info->pages = gcvNULL;
5551 info->pageTable = gcvNULL;
5553 MEMORY_MAP_UNLOCK(Os);
5555 *Address = physical - Os->device->baseAddress;
5558 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5561 return gcvSTATUS_OK;
5566 /* Reference pages. */
5567 for (i = 0; i < pageCount; i++)
5574 for (i = 0; i < pageCount; i++)
5578 get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
5581 /* Flush(clean) the data cache. */
5582 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5583 (gctPOINTER)(gctUINTPTR_T)page_to_phys(pages[i]),
5584 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5589 if (Core == gcvCORE_VG)
5591 /* Allocate pages inside the page table. */
5592 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5593 pageCount * (PAGE_SIZE/4096),
5594 (gctPOINTER *) &pageTable,
5600 /* Allocate pages inside the page table. */
5601 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5602 pageCount * (PAGE_SIZE/4096),
5603 (gctPOINTER *) &pageTable,
5607 /* Fill the page table. */
5608 for (i = 0; i < pageCount; i++)
5611 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5613 phys = page_to_phys(pages[i]);
5616 if (Core == gcvCORE_VG)
5618 /* Get the physical address from page struct. */
5620 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5627 /* Get the physical address from page struct. */
5629 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5634 for (j = 1; j < (PAGE_SIZE/4096); j++)
5636 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5640 gcvLEVEL_INFO, gcvZONE_OS,
5641 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5642 __FUNCTION__, __LINE__,
5643 i, phys, pageTable[i]);
5647 if (Core == gcvCORE_VG)
5649 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5654 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu));
5657 /* Save pointer to page table. */
5658 info->pageTable = pageTable;
5659 info->pages = pages;
5661 *Info = (gctPOINTER) info;
5664 gcvLEVEL_INFO, gcvZONE_OS,
5665 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5666 __FUNCTION__, __LINE__,
5672 offset = (Physical != ~0U)
5673 ? (Physical & ~PAGE_MASK)
5674 : (memory & ~PAGE_MASK);
5676 /* Return address. */
5677 *Address = address + offset;
5680 gcvLEVEL_INFO, gcvZONE_OS,
5681 "%s(%d): Address: 0x%X.",
5682 __FUNCTION__, __LINE__,
5687 status = gcvSTATUS_OK;
5693 if (gcmIS_ERROR(status))
5697 "%s(%d): error occured: %d.",
5698 __FUNCTION__, __LINE__,
5702 /* Release page array. */
5703 if (result > 0 && pages != gcvNULL)
5707 "%s(%d): error: page table is freed.",
5708 __FUNCTION__, __LINE__
5711 for (i = 0; i < result; i++)
5713 if (pages[i] == gcvNULL)
5717 page_cache_release(pages[i]);
5721 if (info!= gcvNULL && pages != gcvNULL)
5725 "%s(%d): error: pages is freed.",
5726 __FUNCTION__, __LINE__
5729 /* Free the page table. */
5731 info->pages = gcvNULL;
5734 /* Release page info struct. */
5735 if (info != gcvNULL)
5739 "%s(%d): error: info is freed.",
5740 __FUNCTION__, __LINE__
5743 /* Free the page info struct. */
5749 MEMORY_MAP_UNLOCK(Os);
5751 /* Return the status. */
5752 if (gcmIS_SUCCESS(status))
5754 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5766 /*******************************************************************************
5768 ** gckOS_UnmapUserMemory
5770 ** Unlock a user buffer and that was previously locked down by
5771 ** gckOS_MapUserMemory.
5775 ** gctPOINTER Memory
5776 ** Pointer to memory to unlock.
5779 ** Size in bytes of the memory to unlock.
5782 ** Information record returned by gckOS_MapUserMemory.
5784 ** gctUINT32_PTR Address
5785 ** The address returned by gckOS_MapUserMemory.
5792 gckOS_UnmapUserMemory(
5795 IN gctPOINTER Memory,
5798 IN gctUINT32 Address
5803 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5804 Os, Core, Memory, Size, Info, Address);
5807 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5810 return gcvSTATUS_OK;
5817 gctUINTPTR_T memory, start, end;
5818 gcsPageInfo_PTR info;
5819 gctSIZE_T pageCount, i;
5820 struct page **pages;
5822 /* Verify the arguments. */
5823 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5824 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5825 gcmkVERIFY_ARGUMENT(Size > 0);
5826 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5830 info = (gcsPageInfo_PTR) Info;
5832 pages = info->pages;
5835 gcvLEVEL_INFO, gcvZONE_OS,
5836 "%s(%d): info=0x%X, pages=0x%X.",
5837 __FUNCTION__, __LINE__,
5841 /* Invalid page array. */
5842 if (pages == gcvNULL && info->pageTable == gcvNULL)
5847 return gcvSTATUS_OK;
5850 memory = (gctUINTPTR_T)Memory;
5851 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5852 start = memory >> PAGE_SHIFT;
5853 pageCount = end - start;
5856 if ((memory + Size) < memory)
5858 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5859 return gcvSTATUS_INVALID_ARGUMENT;
5863 gcvLEVEL_INFO, gcvZONE_OS,
5864 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5865 __FUNCTION__, __LINE__,
5866 memory, pageCount, info->pageTable
5869 MEMORY_MAP_LOCK(Os);
5871 gcmkASSERT(info->pageTable != gcvNULL);
5874 if (Core == gcvCORE_VG)
5876 /* Free the pages from the MMU. */
5877 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5879 pageCount * (PAGE_SIZE/4096)
5885 /* Free the pages from the MMU. */
5886 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5888 pageCount * (PAGE_SIZE/4096)
5892 /* Release the page cache. */
5895 for (i = 0; i < pageCount; i++)
5898 gcvLEVEL_INFO, gcvZONE_OS,
5899 "%s(%d): pages[%d]: 0x%X.",
5900 __FUNCTION__, __LINE__,
5904 if (!PageReserved(pages[i]))
5906 SetPageDirty(pages[i]);
5909 page_cache_release(pages[i]);
5914 status = gcvSTATUS_OK;
5918 if (info != gcvNULL)
5920 /* Free the page array. */
5921 if (info->pages != gcvNULL)
5929 MEMORY_MAP_UNLOCK(Os);
5931 /* Return the status. */
5938 /*******************************************************************************
5940 ** gckOS_GetBaseAddress
5942 ** Get the base address for the physical memory.
5947 ** Pointer to the gckOS object.
5951 ** gctUINT32_PTR BaseAddress
5952 ** Pointer to a variable that will receive the base address.
5955 gckOS_GetBaseAddress(
5957 OUT gctUINT32_PTR BaseAddress
5960 gcmkHEADER_ARG("Os=0x%X", Os);
5962 /* Verify the arguments. */
5963 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5964 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5966 /* Return base address. */
5967 *BaseAddress = Os->device->baseAddress;
5970 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5971 return gcvSTATUS_OK;
5975 gckOS_SuspendInterrupt(
5979 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5983 gckOS_SuspendInterruptEx(
5988 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5990 /* Verify the arguments. */
5991 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5993 disable_irq(Os->device->irqLines[Core]);
5996 return gcvSTATUS_OK;
6000 gckOS_ResumeInterrupt(
6004 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
6008 gckOS_ResumeInterruptEx(
6013 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
6015 /* Verify the arguments. */
6016 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6018 enable_irq(Os->device->irqLines[Core]);
6021 return gcvSTATUS_OK;
6026 IN gctPOINTER Destination,
6027 IN gctCONST_POINTER Source,
6031 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
6032 Destination, Source, Bytes);
6034 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
6035 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
6036 gcmkVERIFY_ARGUMENT(Bytes > 0);
6038 memcpy(Destination, Source, Bytes);
6041 return gcvSTATUS_OK;
6046 IN gctPOINTER Memory,
6050 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
6052 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
6053 gcmkVERIFY_ARGUMENT(Bytes > 0);
6055 memset(Memory, 0, Bytes);
6058 return gcvSTATUS_OK;
6061 /*******************************************************************************
6062 ********************************* Cache Control ********************************
6063 *******************************************************************************/
6065 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
6066 static inline gceSTATUS
6068 gceCACHEOPERATION Type,
6069 unsigned long Start,
6075 case gcvCACHE_CLEAN:
6076 outer_clean_range(Start, End);
6078 case gcvCACHE_INVALIDATE:
6079 outer_inv_range(Start, End);
6081 case gcvCACHE_FLUSH:
6082 outer_flush_range(Start, End);
6085 return gcvSTATUS_INVALID_ARGUMENT;
6088 return gcvSTATUS_OK;
6091 #if gcdENABLE_OUTER_CACHE_PATCH
6092 /*******************************************************************************
6093 ** _HandleOuterCache
6095 ** Handle the outer cache for the specified addresses.
6100 ** Pointer to gckOS object.
6102 ** gctUINT32 ProcessID
6103 ** Process ID Logical belongs.
6105 ** gctPHYS_ADDR Handle
6106 ** Physical address handle. If gcvNULL it is video memory.
6108 ** gctPOINTER Physical
6109 ** Physical address to flush.
6111 ** gctPOINTER Logical
6112 ** Logical address to flush.
6115 ** Size of the address range in bytes to flush.
6117 ** gceOUTERCACHE_OPERATION Type
6118 ** Operation need to be execute.
6123 IN gctUINT32 ProcessID,
6124 IN gctPHYS_ADDR Handle,
6125 IN gctPOINTER Physical,
6126 IN gctPOINTER Logical,
6128 IN gceCACHEOPERATION Type
6132 gctUINT32 i, pageNum;
6133 unsigned long paddr;
6136 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6137 Os, ProcessID, Handle, Logical, Bytes);
6139 if (Physical != gcvNULL)
6141 /* Non paged memory or gcvPOOL_USER surface */
6142 paddr = (unsigned long) Physical;
6143 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6145 else if ((Handle == gcvNULL)
6146 || (Handle != gcvNULL && ((PLINUX_MDL)Handle)->contiguous)
6149 /* Video Memory or contiguous virtual memory */
6150 gcmkONERROR(gckOS_GetPhysicalAddress(Os, Logical, (gctUINT32*)&paddr));
6151 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
6155 /* Non contiguous virtual memory */
6156 vaddr = (gctPOINTER)gcmALIGN_BASE((gctUINTPTR_T)Logical, PAGE_SIZE);
6157 pageNum = GetPageCount(Bytes, 0);
6159 for (i = 0; i < pageNum; i += 1)
6161 gcmkONERROR(_ConvertLogical2Physical(
6163 vaddr + PAGE_SIZE * i,
6169 gcmkONERROR(outer_func(Type, paddr, paddr + PAGE_SIZE));
6177 return gcvSTATUS_OK;
6180 /* Return the status. */
6187 /*******************************************************************************
6190 ** Clean the cache for the specified addresses. The GPU is going to need the
6191 ** data. If the system is allocating memory as non-cachable, this function can
6197 ** Pointer to gckOS object.
6199 ** gctUINT32 ProcessID
6200 ** Process ID Logical belongs.
6202 ** gctPHYS_ADDR Handle
6203 ** Physical address handle. If gcvNULL it is video memory.
6205 ** gctPOINTER Physical
6206 ** Physical address to flush.
6208 ** gctPOINTER Logical
6209 ** Logical address to flush.
6212 ** Size of the address range in bytes to flush.
6217 IN gctUINT32 ProcessID,
6218 IN gctPHYS_ADDR Handle,
6219 IN gctPOINTER Physical,
6220 IN gctPOINTER Logical,
6224 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6225 Os, ProcessID, Handle, Logical, Bytes);
6227 /* Verify the arguments. */
6228 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6229 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6230 gcmkVERIFY_ARGUMENT(Bytes > 0);
6232 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6236 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6237 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
6239 dmac_clean_range(Logical, Logical + Bytes);
6242 #if defined(CONFIG_OUTER_CACHE)
6244 #if gcdENABLE_OUTER_CACHE_PATCH
6245 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_CLEAN);
6247 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6251 #elif defined(CONFIG_MIPS)
6253 dma_cache_wback((unsigned long) Logical, Bytes);
6255 #elif defined(CONFIG_PPC)
6260 dma_sync_single_for_device(
6262 (dma_addr_t)Physical,
6270 return gcvSTATUS_OK;
6273 /*******************************************************************************
6274 ** gckOS_CacheInvalidate
6276 ** Invalidate the cache for the specified addresses. The GPU is going to need
6277 ** data. If the system is allocating memory as non-cachable, this function can
6283 ** Pointer to gckOS object.
6285 ** gctUINT32 ProcessID
6286 ** Process ID Logical belongs.
6288 ** gctPHYS_ADDR Handle
6289 ** Physical address handle. If gcvNULL it is video memory.
6291 ** gctPOINTER Logical
6292 ** Logical address to flush.
6295 ** Size of the address range in bytes to flush.
6298 gckOS_CacheInvalidate(
6300 IN gctUINT32 ProcessID,
6301 IN gctPHYS_ADDR Handle,
6302 IN gctPOINTER Physical,
6303 IN gctPOINTER Logical,
6307 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6308 Os, ProcessID, Handle, Logical, Bytes);
6310 /* Verify the arguments. */
6311 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6312 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6313 gcmkVERIFY_ARGUMENT(Bytes > 0);
6315 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6319 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
6320 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
6322 dmac_inv_range(Logical, Logical + Bytes);
6325 #if defined(CONFIG_OUTER_CACHE)
6327 #if gcdENABLE_OUTER_CACHE_PATCH
6328 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
6330 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6334 #elif defined(CONFIG_MIPS)
6335 dma_cache_inv((unsigned long) Logical, Bytes);
6336 #elif defined(CONFIG_PPC)
6339 dma_sync_single_for_device(
6341 (dma_addr_t)Physical,
6349 return gcvSTATUS_OK;
6352 /*******************************************************************************
6355 ** Clean the cache for the specified addresses and invalidate the lines as
6356 ** well. The GPU is going to need and modify the data. If the system is
6357 ** allocating memory as non-cachable, this function can be ignored.
6362 ** Pointer to gckOS object.
6364 ** gctUINT32 ProcessID
6365 ** Process ID Logical belongs.
6367 ** gctPHYS_ADDR Handle
6368 ** Physical address handle. If gcvNULL it is video memory.
6370 ** gctPOINTER Logical
6371 ** Logical address to flush.
6374 ** Size of the address range in bytes to flush.
6379 IN gctUINT32 ProcessID,
6380 IN gctPHYS_ADDR Handle,
6381 IN gctPOINTER Physical,
6382 IN gctPOINTER Logical,
6386 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6387 Os, ProcessID, Handle, Logical, Bytes);
6389 /* Verify the arguments. */
6390 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6391 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6392 gcmkVERIFY_ARGUMENT(Bytes > 0);
6394 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6397 dmac_flush_range(Logical, Logical + Bytes);
6399 #if defined(CONFIG_OUTER_CACHE)
6401 #if gcdENABLE_OUTER_CACHE_PATCH
6402 _HandleOuterCache(Os, ProcessID, Handle, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6404 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6408 #elif defined(CONFIG_MIPS)
6409 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6410 #elif defined(CONFIG_PPC)
6413 dma_sync_single_for_device(
6415 (dma_addr_t)Physical,
6423 return gcvSTATUS_OK;
6426 /*******************************************************************************
6427 ********************************* Broadcasting *********************************
6428 *******************************************************************************/
6430 /*******************************************************************************
6434 ** System hook for broadcast events from the kernel driver.
6439 ** Pointer to the gckOS object.
6441 ** gckHARDWARE Hardware
6442 ** Pointer to the gckHARDWARE object.
6444 ** gceBROADCAST Reason
6445 ** Reason for the broadcast. Can be one of the following values:
6447 ** gcvBROADCAST_GPU_IDLE
6448 ** Broadcasted when the kernel driver thinks the GPU might be
6449 ** idle. This can be used to handle power management.
6451 ** gcvBROADCAST_GPU_COMMIT
6452 ** Broadcasted when any client process commits a command
6453 ** buffer. This can be used to handle power management.
6455 ** gcvBROADCAST_GPU_STUCK
6456 ** Broadcasted when the kernel driver hits the timeout waiting
6459 ** gcvBROADCAST_FIRST_PROCESS
6460 ** First process is trying to connect to the kernel.
6462 ** gcvBROADCAST_LAST_PROCESS
6463 ** Last process has detached from the kernel.
6472 IN gckHARDWARE Hardware,
6473 IN gceBROADCAST Reason
6478 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6480 /* Verify the arguments. */
6481 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6482 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6486 case gcvBROADCAST_FIRST_PROCESS:
6487 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6490 case gcvBROADCAST_LAST_PROCESS:
6491 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6495 gckHARDWARE_SetPowerManagementState(Hardware,
6496 gcvPOWER_OFF_BROADCAST));
6499 case gcvBROADCAST_GPU_IDLE:
6500 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6504 gckHARDWARE_SetPowerManagementState(Hardware,
6505 #if gcdPOWER_SUSNPEND_WHEN_IDLE
6506 gcvPOWER_SUSPEND_BROADCAST));
6508 gcvPOWER_IDLE_BROADCAST));
6511 /* Add idle process DB. */
6512 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6515 gcvNULL, gcvNULL, 0));
6518 case gcvBROADCAST_GPU_COMMIT:
6519 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6521 /* Add busy process DB. */
6522 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6525 gcvNULL, gcvNULL, 0));
6529 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6532 case gcvBROADCAST_GPU_STUCK:
6533 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6534 #if !gcdENABLE_RECOVERY
6535 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6537 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6540 case gcvBROADCAST_AXI_BUS_ERROR:
6541 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6542 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6543 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6549 return gcvSTATUS_OK;
6552 /* Return the status. */
6557 /*******************************************************************************
6559 ** gckOS_BroadcastHurry
6561 ** The GPU is running too slow.
6566 ** Pointer to the gckOS object.
6568 ** gckHARDWARE Hardware
6569 ** Pointer to the gckHARDWARE object.
6572 ** The higher the number, the higher the urgency to speed up the GPU.
6573 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6580 gckOS_BroadcastHurry(
6582 IN gckHARDWARE Hardware,
6586 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6588 /* Do whatever you need to do to speed up the GPU now. */
6592 return gcvSTATUS_OK;
6595 /*******************************************************************************
6597 ** gckOS_BroadcastCalibrateSpeed
6599 ** Calibrate the speed of the GPU.
6604 ** Pointer to the gckOS object.
6606 ** gckHARDWARE Hardware
6607 ** Pointer to the gckHARDWARE object.
6609 ** gctUINT Idle, Time
6610 ** Idle/Time will give the percentage the GPU is idle, so you can use
6611 ** this to calibrate the working point of the GPU.
6618 gckOS_BroadcastCalibrateSpeed(
6620 IN gckHARDWARE Hardware,
6625 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6626 Os, Hardware, Idle, Time);
6628 /* Do whatever you need to do to callibrate the GPU speed. */
6632 return gcvSTATUS_OK;
6635 /*******************************************************************************
6636 ********************************** Semaphores **********************************
6637 *******************************************************************************/
6639 /*******************************************************************************
6641 ** gckOS_CreateSemaphore
6643 ** Create a semaphore.
6648 ** Pointer to the gckOS object.
6652 ** gctPOINTER * Semaphore
6653 ** Pointer to the variable that will receive the created semaphore.
6656 gckOS_CreateSemaphore(
6658 OUT gctPOINTER * Semaphore
6662 struct semaphore *sem = gcvNULL;
6664 gcmkHEADER_ARG("Os=0x%X", Os);
6666 /* Verify the arguments. */
6667 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6668 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6670 /* Allocate the semaphore structure. */
6671 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6674 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6677 /* Initialize the semaphore. */
6680 /* Return to caller. */
6681 *Semaphore = (gctPOINTER) sem;
6685 return gcvSTATUS_OK;
6688 /* Return the status. */
6693 /*******************************************************************************
6695 ** gckOS_AcquireSemaphore
6697 ** Acquire a semaphore.
6702 ** Pointer to the gckOS object.
6704 ** gctPOINTER Semaphore
6705 ** Pointer to the semaphore thet needs to be acquired.
6712 gckOS_AcquireSemaphore(
6714 IN gctPOINTER Semaphore
6719 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6721 /* Verify the arguments. */
6722 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6723 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6725 /* Acquire the semaphore. */
6726 if (down_interruptible((struct semaphore *) Semaphore))
6728 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6733 return gcvSTATUS_OK;
6736 /* Return the status. */
6741 /*******************************************************************************
6743 ** gckOS_TryAcquireSemaphore
6745 ** Try to acquire a semaphore.
6750 ** Pointer to the gckOS object.
6752 ** gctPOINTER Semaphore
6753 ** Pointer to the semaphore thet needs to be acquired.
6760 gckOS_TryAcquireSemaphore(
6762 IN gctPOINTER Semaphore
6767 gcmkHEADER_ARG("Os=0x%x", Os);
6769 /* Verify the arguments. */
6770 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6771 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6773 /* Acquire the semaphore. */
6774 if (down_trylock((struct semaphore *) Semaphore))
6777 status = gcvSTATUS_TIMEOUT;
6784 return gcvSTATUS_OK;
6787 /*******************************************************************************
6789 ** gckOS_ReleaseSemaphore
6791 ** Release a previously acquired semaphore.
6796 ** Pointer to the gckOS object.
6798 ** gctPOINTER Semaphore
6799 ** Pointer to the semaphore thet needs to be released.
6806 gckOS_ReleaseSemaphore(
6808 IN gctPOINTER Semaphore
6811 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6813 /* Verify the arguments. */
6814 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6815 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6817 /* Release the semaphore. */
6818 up((struct semaphore *) Semaphore);
6822 return gcvSTATUS_OK;
6825 /*******************************************************************************
6827 ** gckOS_DestroySemaphore
6829 ** Destroy a semaphore.
6834 ** Pointer to the gckOS object.
6836 ** gctPOINTER Semaphore
6837 ** Pointer to the semaphore thet needs to be destroyed.
6844 gckOS_DestroySemaphore(
6846 IN gctPOINTER Semaphore
6849 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6851 /* Verify the arguments. */
6852 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6853 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6855 /* Free the sempahore structure. */
6860 return gcvSTATUS_OK;
6863 /*******************************************************************************
6865 ** gckOS_GetProcessID
6867 ** Get current process ID.
6875 ** gctUINT32_PTR ProcessID
6876 ** Pointer to the variable that receives the process ID.
6880 OUT gctUINT32_PTR ProcessID
6883 /* Get process ID. */
6884 if (ProcessID != gcvNULL)
6886 *ProcessID = _GetProcessID();
6890 return gcvSTATUS_OK;
6893 /*******************************************************************************
6895 ** gckOS_GetThreadID
6897 ** Get current thread ID.
6905 ** gctUINT32_PTR ThreadID
6906 ** Pointer to the variable that receives the thread ID.
6910 OUT gctUINT32_PTR ThreadID
6913 /* Get thread ID. */
6914 if (ThreadID != gcvNULL)
6916 *ThreadID = _GetThreadID();
6920 return gcvSTATUS_OK;
6923 /*******************************************************************************
6925 ** gckOS_SetGPUPower
6927 ** Set the power of the GPU on or off.
6932 ** Pointer to a gckOS object.
6935 ** GPU whose power is set.
6938 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6941 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6955 struct clk *clk_3dcore = Os->device->clk_3d_core;
6956 struct clk *clk_3dshader = Os->device->clk_3d_shader;
6957 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0)
6958 struct clk *clk_3d_axi = Os->device->clk_3d_axi;
6960 struct clk *clk_2dcore = Os->device->clk_2d_core;
6961 struct clk *clk_2d_axi = Os->device->clk_2d_axi;
6962 struct clk *clk_vg_axi = Os->device->clk_vg_axi;
6963 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6967 gctBOOL oldClockState = gcvFALSE;
6968 gctBOOL oldPowerState = gcvFALSE;
6970 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6972 if (Os->device->kernels[Core] != NULL)
6975 if (Core == gcvCORE_VG)
6977 oldClockState = Os->device->kernels[Core]->vg->hardware->clockState;
6978 oldPowerState = Os->device->kernels[Core]->vg->hardware->powerState;
6983 oldClockState = Os->device->kernels[Core]->hardware->clockState;
6984 oldPowerState = Os->device->kernels[Core]->hardware->powerState;
6989 if((Power == gcvTRUE) && (oldPowerState == gcvFALSE))
6991 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
6992 if(!IS_ERR(Os->device->gpu_regulator)) {
6993 ret = regulator_enable(Os->device->gpu_regulator);
6995 gckOS_Print("%s(%d): fail to enable pu regulator %d!\n",
6996 __FUNCTION__, __LINE__, ret);
6999 imx_gpc_power_up_pu(true);
7003 pm_runtime_get_sync(Os->device->pmdev);
7007 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7008 if (Clock == gcvTRUE) {
7009 if (oldClockState == gcvFALSE) {
7012 clk_enable(clk_3dcore);
7014 clk_enable(clk_3dshader);
7017 clk_enable(clk_2dcore);
7018 clk_enable(clk_2d_axi);
7021 clk_enable(clk_2dcore);
7022 clk_enable(clk_vg_axi);
7029 if (oldClockState == gcvTRUE) {
7033 clk_disable(clk_3dshader);
7034 clk_disable(clk_3dcore);
7037 clk_disable(clk_2dcore);
7038 clk_disable(clk_2d_axi);
7041 clk_disable(clk_2dcore);
7042 clk_disable(clk_vg_axi);
7050 if (Clock == gcvTRUE) {
7051 if (oldClockState == gcvFALSE) {
7054 clk_prepare(clk_3dcore);
7055 clk_enable(clk_3dcore);
7056 clk_prepare(clk_3dshader);
7057 clk_enable(clk_3dshader);
7058 clk_prepare(clk_3d_axi);
7059 clk_enable(clk_3d_axi);
7062 clk_prepare(clk_2dcore);
7063 clk_enable(clk_2dcore);
7064 clk_prepare(clk_2d_axi);
7065 clk_enable(clk_2d_axi);
7068 clk_prepare(clk_2dcore);
7069 clk_enable(clk_2dcore);
7070 clk_prepare(clk_vg_axi);
7071 clk_enable(clk_vg_axi);
7078 if (oldClockState == gcvTRUE) {
7081 clk_disable(clk_3dshader);
7082 clk_unprepare(clk_3dshader);
7083 clk_disable(clk_3dcore);
7084 clk_unprepare(clk_3dcore);
7085 clk_disable(clk_3d_axi);
7086 clk_unprepare(clk_3d_axi);
7089 clk_disable(clk_2dcore);
7090 clk_unprepare(clk_2dcore);
7091 clk_disable(clk_2d_axi);
7092 clk_unprepare(clk_2d_axi);
7095 clk_disable(clk_2dcore);
7096 clk_unprepare(clk_2dcore);
7097 clk_disable(clk_vg_axi);
7098 clk_unprepare(clk_vg_axi);
7106 if((Power == gcvFALSE) && (oldPowerState == gcvTRUE))
7109 pm_runtime_put_sync(Os->device->pmdev);
7112 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) || LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7113 if(!IS_ERR(Os->device->gpu_regulator))
7114 regulator_disable(Os->device->gpu_regulator);
7116 imx_gpc_power_up_pu(false);
7120 /* TODO: Put your code here. */
7122 return gcvSTATUS_OK;
7125 /*******************************************************************************
7134 ** Pointer to a gckOS object.
7137 ** GPU whose power is set.
7149 #if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0)
7150 #define SRC_SCR_OFFSET 0
7151 #define BP_SRC_SCR_GPU3D_RST 1
7152 #define BP_SRC_SCR_GPU2D_RST 4
7153 void __iomem *src_base = IO_ADDRESS(SRC_BASE_ADDR);
7154 gctUINT32 bit_offset,val;
7156 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
7158 if(Core == gcvCORE_MAJOR) {
7159 bit_offset = BP_SRC_SCR_GPU3D_RST;
7160 } else if((Core == gcvCORE_VG)
7161 ||(Core == gcvCORE_2D)) {
7162 bit_offset = BP_SRC_SCR_GPU2D_RST;
7164 return gcvSTATUS_INVALID_CONFIG;
7166 val = __raw_readl(src_base + SRC_SCR_OFFSET);
7167 val &= ~(1 << (bit_offset));
7168 val |= (1 << (bit_offset));
7169 __raw_writel(val, src_base + SRC_SCR_OFFSET);
7171 while ((__raw_readl(src_base + SRC_SCR_OFFSET) &
7172 (1 << (bit_offset))) != 0) {
7176 #elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
7177 struct reset_control *rstc = Os->device->rstc[Core];
7179 reset_control_reset(rstc);
7181 imx_src_reset_gpu((int)Core);
7183 return gcvSTATUS_OK;
7186 /*******************************************************************************
7188 ** gckOS_PrepareGPUFrequency
7190 ** Prepare to set GPU frequency and voltage.
7195 ** Pointer to a gckOS object.
7198 ** GPU whose frequency and voltage will be set.
7205 gckOS_PrepareGPUFrequency(
7210 return gcvSTATUS_OK;
7213 /*******************************************************************************
7215 ** gckOS_FinishGPUFrequency
7217 ** Finish GPU frequency setting.
7222 ** Pointer to a gckOS object.
7225 ** GPU whose frequency and voltage is set.
7232 gckOS_FinishGPUFrequency(
7237 return gcvSTATUS_OK;
7240 /*******************************************************************************
7242 ** gckOS_QueryGPUFrequency
7244 ** Query the current frequency of the GPU.
7249 ** Pointer to a gckOS object.
7252 ** GPU whose power is set.
7254 ** gctUINT32 * Frequency
7255 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
7258 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
7265 gckOS_QueryGPUFrequency(
7268 OUT gctUINT32 * Frequency,
7269 OUT gctUINT8 * Scale
7272 return gcvSTATUS_OK;
7275 /*******************************************************************************
7277 ** gckOS_SetGPUFrequency
7279 ** Set frequency and voltage of the GPU.
7281 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
7282 ** a real frequency according to this scale and board's configure.
7284 ** 2. BSP should find a suitable voltage for this frequency.
7286 ** 3. BSP must make sure setting take effect before this function returns.
7291 ** Pointer to a gckOS object.
7294 ** GPU whose power is set.
7297 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
7298 ** full frequency and 64 means 64/64 of full frequency.
7305 gckOS_SetGPUFrequency(
7311 return gcvSTATUS_OK;
7314 /*----------------------------------------------------------------------------*/
7315 /*----- Profile --------------------------------------------------------------*/
7318 gckOS_GetProfileTick(
7319 OUT gctUINT64_PTR Tick
7322 struct timespec time;
7324 ktime_get_ts(&time);
7326 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
7328 return gcvSTATUS_OK;
7332 gckOS_QueryProfileTickRate(
7333 OUT gctUINT64_PTR TickRate
7336 struct timespec res;
7338 hrtimer_get_res(CLOCK_MONOTONIC, &res);
7340 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
7342 return gcvSTATUS_OK;
7350 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
7351 return div_u64(Ticks, 1000000);
7353 gctUINT64 rem = Ticks;
7354 gctUINT64 b = 1000000;
7355 gctUINT64 res, d = 1;
7356 gctUINT32 high = rem >> 32;
7358 /* Reduce the thing a bit first */
7360 if (high >= 1000000)
7363 res = (gctUINT64) high << 32;
7364 rem -= (gctUINT64) (high * 1000000) << 32;
7367 while (((gctINT64) b > 0) && (b < rem))
7386 return (gctUINT32) res;
7390 /******************************************************************************\
7391 ******************************* Signal Management ******************************
7392 \******************************************************************************/
7395 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
7397 /*******************************************************************************
7399 ** gckOS_CreateSignal
7401 ** Create a new signal.
7406 ** Pointer to an gckOS object.
7408 ** gctBOOL ManualReset
7409 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7410 ** order to set the signal to nonsignaled state.
7411 ** If set to gcvFALSE, the signal will automatically be set to
7412 ** nonsignaled state by gckOS_WaitSignal function.
7416 ** gctSIGNAL * Signal
7417 ** Pointer to a variable receiving the created gctSIGNAL.
7422 IN gctBOOL ManualReset,
7423 OUT gctSIGNAL * Signal
7427 gcsSIGNAL_PTR signal;
7429 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
7431 /* Verify the arguments. */
7432 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7433 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7435 /* Create an event structure. */
7436 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
7438 if (signal == gcvNULL)
7440 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
7443 /* Save the process ID. */
7444 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
7445 signal->manualReset = ManualReset;
7446 signal->hardware = gcvNULL;
7447 init_completion(&signal->obj);
7448 atomic_set(&signal->ref, 1);
7450 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
7452 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
7454 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
7455 return gcvSTATUS_OK;
7458 if (signal != gcvNULL)
7468 gckOS_SignalQueryHardware(
7470 IN gctSIGNAL Signal,
7471 OUT gckHARDWARE * Hardware
7475 gcsSIGNAL_PTR signal;
7477 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7479 /* Verify the arguments. */
7480 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7481 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7482 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7484 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7486 *Hardware = signal->hardware;
7489 return gcvSTATUS_OK;
7496 gckOS_SignalSetHardware(
7498 IN gctSIGNAL Signal,
7499 IN gckHARDWARE Hardware
7503 gcsSIGNAL_PTR signal;
7505 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7507 /* Verify the arguments. */
7508 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7509 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7511 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7513 signal->hardware = Hardware;
7516 return gcvSTATUS_OK;
7522 /*******************************************************************************
7524 ** gckOS_DestroySignal
7526 ** Destroy a signal.
7531 ** Pointer to an gckOS object.
7534 ** Pointer to the gctSIGNAL.
7541 gckOS_DestroySignal(
7547 gcsSIGNAL_PTR signal;
7548 gctBOOL acquired = gcvFALSE;
7550 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7552 /* Verify the arguments. */
7553 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7554 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7556 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7559 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7561 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7563 if (atomic_dec_and_test(&signal->ref))
7565 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7567 /* Free the sgianl. */
7571 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7572 acquired = gcvFALSE;
7576 return gcvSTATUS_OK;
7581 /* Release the mutex. */
7582 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7589 /*******************************************************************************
7593 ** Set a state of the specified signal.
7598 ** Pointer to an gckOS object.
7601 ** Pointer to the gctSIGNAL.
7604 ** If gcvTRUE, the signal will be set to signaled state.
7605 ** If gcvFALSE, the signal will be set to nonsignaled state.
7614 IN gctSIGNAL Signal,
7619 gcsSIGNAL_PTR signal;
7620 gctBOOL acquired = gcvFALSE;
7622 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7624 /* Verify the arguments. */
7625 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7626 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7628 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7631 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7633 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7637 /* unbind the signal from hardware. */
7638 signal->hardware = gcvNULL;
7640 /* Set the event to a signaled state. */
7641 complete(&signal->obj);
7645 /* Set the event to an unsignaled state. */
7646 INIT_COMPLETION(signal->obj);
7649 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7650 acquired = gcvFALSE;
7654 return gcvSTATUS_OK;
7659 /* Release the mutex. */
7660 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7671 IN gctHANDLE Process,
7677 struct task_struct * userTask;
7678 struct siginfo info;
7680 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7682 if (userTask != gcvNULL)
7685 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7688 info.si_ptr = (gctPOINTER) Signal;
7690 /* Signals with numbers between 32 and 63 are real-time,
7691 send a real-time signal to the user process. */
7692 result = send_sig_info(48, &info, userTask);
7694 printk("gckOS_SetSignalVG:0x%x\n", result);
7698 status = gcvSTATUS_GENERIC_IO;
7702 "%s(%d): an error has occurred.\n",
7703 __FUNCTION__, __LINE__
7708 status = gcvSTATUS_OK;
7713 status = gcvSTATUS_GENERIC_IO;
7717 "%s(%d): an error has occurred.\n",
7718 __FUNCTION__, __LINE__
7722 /* Return status. */
7727 /*******************************************************************************
7731 ** Set the specified signal which is owned by a process to signaled state.
7736 ** Pointer to an gckOS object.
7739 ** Pointer to the gctSIGNAL.
7741 ** gctHANDLE Process
7742 ** Handle of process owning the signal.
7751 IN gctSIGNAL Signal,
7752 IN gctHANDLE Process
7758 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7759 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7761 /* Map the signal into kernel space. */
7762 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7765 status = gckOS_Signal(Os, signal, gcvTRUE);
7767 /* Unmap the signal */
7768 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7774 /* Return the status. */
7779 /*******************************************************************************
7783 ** Wait for a signal to become signaled.
7788 ** Pointer to an gckOS object.
7791 ** Pointer to the gctSIGNAL.
7794 ** Number of milliseconds to wait.
7795 ** Pass the value of gcvINFINITE for an infinite wait.
7804 IN gctSIGNAL Signal,
7808 gceSTATUS status = gcvSTATUS_OK;
7809 gcsSIGNAL_PTR signal;
7811 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7813 /* Verify the arguments. */
7814 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7815 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7817 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7819 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7823 spin_lock_irq(&signal->obj.wait.lock);
7825 if (signal->obj.done)
7827 if (!signal->manualReset)
7829 signal->obj.done = 0;
7832 status = gcvSTATUS_OK;
7836 status = gcvSTATUS_TIMEOUT;
7840 /* Convert wait to milliseconds. */
7841 #if gcdDETECT_TIMEOUT
7842 gctINT timeout = (Wait == gcvINFINITE)
7843 ? gcdINFINITE_TIMEOUT * HZ / 1000
7846 gctUINT complained = 0;
7848 gctINT timeout = (Wait == gcvINFINITE)
7849 ? MAX_SCHEDULE_TIMEOUT
7853 DECLARE_WAITQUEUE(wait, current);
7854 wait.flags |= WQ_FLAG_EXCLUSIVE;
7855 __add_wait_queue_tail(&signal->obj.wait, &wait);
7859 if (signal_pending(current))
7861 /* Interrupt received. */
7862 status = gcvSTATUS_INTERRUPTED;
7866 __set_current_state(TASK_INTERRUPTIBLE);
7867 spin_unlock_irq(&signal->obj.wait.lock);
7868 timeout = schedule_timeout(timeout);
7869 spin_lock_irq(&signal->obj.wait.lock);
7871 if (signal->obj.done)
7873 if (!signal->manualReset)
7875 signal->obj.done = 0;
7878 status = gcvSTATUS_OK;
7882 #if gcdDETECT_TIMEOUT
7883 if ((Wait == gcvINFINITE) && (timeout == 0))
7885 gctUINT32 dmaAddress1, dmaAddress2;
7886 gctUINT32 dmaState1, dmaState2;
7888 dmaState1 = dmaState2 =
7889 dmaAddress1 = dmaAddress2 = 0;
7891 /* Verify whether DMA is running. */
7892 gcmkVERIFY_OK(_VerifyDMA(
7893 Os, &dmaAddress1, &dmaAddress2, &dmaState1, &dmaState2
7896 #if gcdDETECT_DMA_ADDRESS
7897 /* Dump only if DMA appears stuck. */
7899 (dmaAddress1 == dmaAddress2)
7900 #if gcdDETECT_DMA_STATE
7901 && (dmaState1 == dmaState2)
7906 /* Increment complain count. */
7909 gcmkVERIFY_OK(_DumpGPUState(Os, gcvCORE_MAJOR));
7912 "%s(%d): signal 0x%X; forced message flush (%d).",
7913 __FUNCTION__, __LINE__, Signal, complained
7916 /* Flush the debug cache. */
7917 gcmkDEBUGFLUSH(dmaAddress2);
7920 /* Reset timeout. */
7921 timeout = gcdINFINITE_TIMEOUT * HZ / 1000;
7928 status = gcvSTATUS_TIMEOUT;
7933 __remove_wait_queue(&signal->obj.wait, &wait);
7935 #if gcdDETECT_TIMEOUT
7939 "%s(%d): signal=0x%X; waiting done; status=%d",
7940 __FUNCTION__, __LINE__, Signal, status
7946 spin_unlock_irq(&signal->obj.wait.lock);
7949 /* Return status. */
7950 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7954 /*******************************************************************************
7958 ** Map a signal in to the current process space.
7963 ** Pointer to an gckOS object.
7966 ** Pointer to tha gctSIGNAL to map.
7968 ** gctHANDLE Process
7969 ** Handle of process owning the signal.
7973 ** gctSIGNAL * MappedSignal
7974 ** Pointer to a variable receiving the mapped gctSIGNAL.
7979 IN gctSIGNAL Signal,
7980 IN gctHANDLE Process,
7981 OUT gctSIGNAL * MappedSignal
7985 gcsSIGNAL_PTR signal;
7986 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7988 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7989 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7991 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7993 if(atomic_inc_return(&signal->ref) <= 1)
7995 /* The previous value is 0, it has been deleted. */
7996 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7999 *MappedSignal = (gctSIGNAL) Signal;
8002 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
8003 return gcvSTATUS_OK;
8010 /*******************************************************************************
8012 ** gckOS_UnmapSignal
8019 ** Pointer to an gckOS object.
8022 ** Pointer to that gctSIGNAL mapped.
8030 return gckOS_DestroySignal(Os, Signal);
8033 /*******************************************************************************
8035 ** gckOS_CreateUserSignal
8037 ** Create a new signal to be used in the user space.
8042 ** Pointer to an gckOS object.
8044 ** gctBOOL ManualReset
8045 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
8046 ** order to set the signal to nonsignaled state.
8047 ** If set to gcvFALSE, the signal will automatically be set to
8048 ** nonsignaled state by gckOS_WaitSignal function.
8052 ** gctINT * SignalID
8053 ** Pointer to a variable receiving the created signal's ID.
8056 gckOS_CreateUserSignal(
8058 IN gctBOOL ManualReset,
8059 OUT gctINT * SignalID
8065 /* Create a new signal. */
8066 status = gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal);
8067 *SignalID = (gctINT) signal;
8072 /*******************************************************************************
8074 ** gckOS_DestroyUserSignal
8076 ** Destroy a signal to be used in the user space.
8081 ** Pointer to an gckOS object.
8091 gckOS_DestroyUserSignal(
8096 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
8099 /*******************************************************************************
8101 ** gckOS_WaitUserSignal
8103 ** Wait for a signal used in the user mode to become signaled.
8108 ** Pointer to an gckOS object.
8114 ** Number of milliseconds to wait.
8115 ** Pass the value of gcvINFINITE for an infinite wait.
8122 gckOS_WaitUserSignal(
8128 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
8131 /*******************************************************************************
8133 ** gckOS_SignalUserSignal
8135 ** Set a state of the specified signal to be used in the user space.
8140 ** Pointer to an gckOS object.
8146 ** If gcvTRUE, the signal will be set to signaled state.
8147 ** If gcvFALSE, the signal will be set to nonsignaled state.
8154 gckOS_SignalUserSignal(
8160 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
8165 gckOS_CreateSemaphoreVG(
8167 OUT gctSEMAPHORE * Semaphore
8171 struct semaphore * newSemaphore;
8173 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8174 /* Verify the arguments. */
8175 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8176 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8180 /* Allocate the semaphore structure. */
8181 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
8182 if (newSemaphore == gcvNULL)
8184 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
8187 /* Initialize the semaphore. */
8188 sema_init(newSemaphore, 0);
8190 /* Set the handle. */
8191 * Semaphore = (gctSEMAPHORE) newSemaphore;
8194 status = gcvSTATUS_OK;
8199 /* Return the status. */
8205 gckOS_IncrementSemaphore(
8207 IN gctSEMAPHORE Semaphore
8210 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8211 /* Verify the arguments. */
8212 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8213 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8215 /* Increment the semaphore's count. */
8216 up((struct semaphore *) Semaphore);
8220 return gcvSTATUS_OK;
8224 gckOS_DecrementSemaphore(
8226 IN gctSEMAPHORE Semaphore
8232 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
8233 /* Verify the arguments. */
8234 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8235 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
8239 /* Decrement the semaphore's count. If the count is zero, wait
8240 until it gets incremented. */
8241 result = down_interruptible((struct semaphore *) Semaphore);
8243 /* Signal received? */
8246 status = gcvSTATUS_TERMINATE;
8251 status = gcvSTATUS_OK;
8256 /* Return the status. */
8260 /*******************************************************************************
8264 ** Set the specified signal to signaled state.
8269 ** Pointer to the gckOS object.
8271 ** gctHANDLE Process
8272 ** Handle of process owning the signal.
8275 ** Pointer to the gctSIGNAL.
8284 IN gctHANDLE Process,
8290 struct task_struct * userTask;
8291 struct siginfo info;
8293 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
8295 if (userTask != gcvNULL)
8298 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
8301 info.si_ptr = (gctPOINTER) Signal;
8303 /* Signals with numbers between 32 and 63 are real-time,
8304 send a real-time signal to the user process. */
8305 result = send_sig_info(48, &info, userTask);
8310 status = gcvSTATUS_GENERIC_IO;
8314 "%s(%d): an error has occurred.\n",
8315 __FUNCTION__, __LINE__
8320 status = gcvSTATUS_OK;
8325 status = gcvSTATUS_GENERIC_IO;
8329 "%s(%d): an error has occurred.\n",
8330 __FUNCTION__, __LINE__
8334 /* Return status. */
8338 /******************************************************************************\
8339 ******************************** Thread Object *********************************
8340 \******************************************************************************/
8345 IN gctTHREADFUNC ThreadFunction,
8346 IN gctPOINTER ThreadParameter,
8347 OUT gctTHREAD * Thread
8351 struct task_struct * thread;
8353 gcmkHEADER_ARG("Os=0x%X ", Os);
8354 /* Verify the arguments. */
8355 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8356 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
8357 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8361 /* Create the thread. */
8362 thread = kthread_create(
8365 "Vivante Kernel Thread"
8371 status = gcvSTATUS_GENERIC_IO;
8375 /* Start the thread. */
8376 wake_up_process(thread);
8378 /* Set the thread handle. */
8379 * Thread = (gctTHREAD) thread;
8382 status = gcvSTATUS_OK;
8387 /* Return the status. */
8397 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8398 /* Verify the arguments. */
8399 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8400 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8402 /* Thread should have already been enabled to terminate. */
8403 kthread_stop((struct task_struct *) Thread);
8407 return gcvSTATUS_OK;
8416 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
8417 /* Verify the arguments. */
8418 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8419 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
8423 return gcvSTATUS_OK;
8427 /******************************************************************************\
8428 ******************************** Software Timer ********************************
8429 \******************************************************************************/
8433 struct work_struct * work
8436 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
8438 gctTIMERFUNCTION function = timer->function;
8440 function(timer->data);
8443 /*******************************************************************************
8445 ** gckOS_CreateTimer
8447 ** Create a software timer.
8452 ** Pointer to the gckOS object.
8454 ** gctTIMERFUNCTION Function.
8455 ** Pointer to a call back function which will be called when timer is
8459 ** Private data which will be passed to call back function.
8463 ** gctPOINTER * Timer
8464 ** Pointer to a variable receiving the created timer.
8469 IN gctTIMERFUNCTION Function,
8471 OUT gctPOINTER * Timer
8475 gcsOSTIMER_PTR pointer;
8476 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
8478 /* Verify the arguments. */
8479 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8480 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8482 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
8484 pointer->function = Function;
8485 pointer->data = Data;
8487 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
8492 return gcvSTATUS_OK;
8499 /*******************************************************************************
8501 ** gckOS_DestroyTimer
8503 ** Destory a software timer.
8508 ** Pointer to the gckOS object.
8511 ** Pointer to the timer to be destoryed.
8523 gcsOSTIMER_PTR timer;
8524 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8526 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8527 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8529 timer = (gcsOSTIMER_PTR)Timer;
8531 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8532 cancel_delayed_work_sync(&timer->work);
8534 cancel_delayed_work(&timer->work);
8535 flush_workqueue(Os->workqueue);
8538 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8541 return gcvSTATUS_OK;
8544 /*******************************************************************************
8548 ** Schedule a software timer.
8553 ** Pointer to the gckOS object.
8556 ** Pointer to the timer to be scheduled.
8559 ** Delay in milliseconds.
8568 IN gctPOINTER Timer,
8572 gcsOSTIMER_PTR timer;
8574 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8576 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8577 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8578 gcmkVERIFY_ARGUMENT(Delay != 0);
8580 timer = (gcsOSTIMER_PTR)Timer;
8582 if (unlikely(delayed_work_pending(&timer->work)))
8584 cancel_delayed_work(&timer->work);
8587 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8590 return gcvSTATUS_OK;
8593 /*******************************************************************************
8597 ** Cancel a unscheduled timer.
8602 ** Pointer to the gckOS object.
8605 ** Pointer to the timer to be cancel.
8617 gcsOSTIMER_PTR timer;
8618 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8620 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8621 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8623 timer = (gcsOSTIMER_PTR)Timer;
8625 cancel_delayed_work(&timer->work);
8628 return gcvSTATUS_OK;
8633 gckOS_DumpCallStack(
8637 gcmkHEADER_ARG("Os=0x%X", Os);
8639 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8644 return gcvSTATUS_OK;
8649 gckOS_GetProcessNameByPid(
8651 IN gctSIZE_T Length,
8652 OUT gctUINT8_PTR String
8655 struct task_struct *task;
8657 /* Get the task_struct of the task with pid. */
8660 task = FIND_TASK_BY_PID(Pid);
8662 if (task == gcvNULL)
8665 return gcvSTATUS_NOT_FOUND;
8668 /* Get name of process. */
8669 strncpy(String, task->comm, Length);
8673 return gcvSTATUS_OK;
8676 #if gcdANDROID_NATIVE_FENCE_SYNC
8679 gckOS_CreateSyncPoint(
8681 OUT gctSYNC_POINT * SyncPoint
8685 gcsSYNC_POINT_PTR syncPoint;
8687 gcmkHEADER_ARG("Os=0x%X", Os);
8689 /* Verify the arguments. */
8690 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8692 /* Create an sync point structure. */
8693 syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
8694 sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
8696 if (syncPoint == gcvNULL)
8698 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8701 /* Initialize the sync point. */
8702 atomic_set(&syncPoint->ref, 1);
8703 atomic_set(&syncPoint->state, 0);
8705 gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
8707 *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
8709 gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
8710 return gcvSTATUS_OK;
8713 if (syncPoint != gcvNULL)
8723 gckOS_ReferenceSyncPoint(
8725 IN gctSYNC_POINT SyncPoint
8729 gcsSYNC_POINT_PTR syncPoint;
8731 gcmkHEADER_ARG("Os=0x%X", Os);
8733 /* Verify the arguments. */
8734 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8735 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8738 _QueryIntegerId(&Os->syncPointDB,
8739 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8740 (gctPOINTER)&syncPoint));
8742 /* Initialize the sync point. */
8743 atomic_inc(&syncPoint->ref);
8746 return gcvSTATUS_OK;
8754 gckOS_DestroySyncPoint(
8756 IN gctSYNC_POINT SyncPoint
8760 gcsSYNC_POINT_PTR syncPoint;
8761 gctBOOL acquired = gcvFALSE;
8763 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8765 /* Verify the arguments. */
8766 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8767 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8769 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8773 _QueryIntegerId(&Os->syncPointDB,
8774 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8775 (gctPOINTER)&syncPoint));
8777 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8779 if (atomic_dec_and_test(&syncPoint->ref))
8781 gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
8783 /* Free the sgianl. */
8784 syncPoint->timeline = gcvNULL;
8788 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8789 acquired = gcvFALSE;
8793 return gcvSTATUS_OK;
8798 /* Release the mutex. */
8799 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8807 gckOS_SignalSyncPoint(
8809 IN gctSYNC_POINT SyncPoint
8813 gcsSYNC_POINT_PTR syncPoint;
8814 gctBOOL acquired = gcvFALSE;
8816 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8818 /* Verify the arguments. */
8819 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8820 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8822 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8826 _QueryIntegerId(&Os->syncPointDB,
8827 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8828 (gctPOINTER)&syncPoint));
8830 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8833 atomic_set(&syncPoint->state, gcvTRUE);
8835 /* Signal timeline. */
8836 if (syncPoint->timeline)
8838 sync_timeline_signal(syncPoint->timeline);
8841 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8842 acquired = gcvFALSE;
8846 return gcvSTATUS_OK;
8851 /* Release the mutex. */
8852 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8860 gckOS_QuerySyncPoint(
8862 IN gctSYNC_POINT SyncPoint,
8863 OUT gctBOOL_PTR State
8867 gcsSYNC_POINT_PTR syncPoint;
8869 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8871 /* Verify the arguments. */
8872 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8873 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8876 _QueryIntegerId(&Os->syncPointDB,
8877 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8878 (gctPOINTER)&syncPoint));
8880 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8883 *State = atomic_read(&syncPoint->state);
8886 gcmkFOOTER_ARG("*State=%d", *State);
8887 return gcvSTATUS_OK;
8895 gckOS_CreateSyncTimeline(
8897 OUT gctHANDLE * Timeline
8900 struct viv_sync_timeline * timeline;
8902 /* Create viv sync timeline. */
8903 timeline = viv_sync_timeline_create("viv timeline", Os);
8905 if (timeline == gcvNULL)
8907 /* Out of memory. */
8908 return gcvSTATUS_OUT_OF_MEMORY;
8911 *Timeline = (gctHANDLE) timeline;
8912 return gcvSTATUS_OK;
8916 gckOS_DestroySyncTimeline(
8918 IN gctHANDLE Timeline
8921 struct viv_sync_timeline * timeline;
8922 gcmkASSERT(Timeline != gcvNULL);
8924 /* Destroy timeline. */
8925 timeline = (struct viv_sync_timeline *) Timeline;
8926 sync_timeline_destroy(&timeline->obj);
8928 return gcvSTATUS_OK;
8932 gckOS_CreateNativeFence(
8934 IN gctHANDLE Timeline,
8935 IN gctSYNC_POINT SyncPoint,
8936 OUT gctINT * FenceFD
8940 struct viv_sync_timeline *timeline;
8941 struct sync_pt * pt = gcvNULL;
8942 struct sync_fence * fence;
8944 gcsSYNC_POINT_PTR syncPoint;
8947 gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
8948 Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
8951 _QueryIntegerId(&Os->syncPointDB,
8952 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8953 (gctPOINTER)&syncPoint));
8955 /* Cast timeline. */
8956 timeline = (struct viv_sync_timeline *) Timeline;
8958 fd = get_unused_fd();
8962 /* Out of resources. */
8963 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
8966 /* Create viv_sync_pt. */
8967 pt = viv_sync_pt_create(timeline, SyncPoint);
8971 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8974 /* Reference sync_timeline. */
8975 syncPoint->timeline = &timeline->obj;
8977 /* Build fence name. */
8978 snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
8980 /* Create sync_fence. */
8981 fence = sync_fence_create(name, pt);
8985 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8988 /* Install fence to fd. */
8989 sync_fence_install(fence, fd);
8992 gcmkFOOTER_ARG("*FenceFD=%d", fd);
8993 return gcvSTATUS_OK;
8996 /* Error roll back. */