1 /****************************************************************************
3 * Copyright (C) 2005 - 2014 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>
26 #include <linux/mman.h>
27 #include <asm/atomic.h>
28 #include <linux/dma-mapping.h>
29 #include <linux/slab.h>
30 #include <linux/workqueue.h>
31 #include <linux/irqflags.h>
32 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
33 #include <linux/math64.h>
35 #include <linux/delay.h>
37 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
38 #include <linux/anon_inodes.h>
41 #if gcdANDROID_NATIVE_FENCE_SYNC
42 #include <linux/file.h>
43 #include "gc_hal_kernel_sync.h"
46 #define _GC_OBJ_ZONE gcvZONE_OS
48 #include "gc_hal_kernel_allocator.h"
50 #define MEMORY_LOCK(os) \
51 gcmkVERIFY_OK(gckOS_AcquireMutex( \
56 #define MEMORY_UNLOCK(os) \
57 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
59 #define MEMORY_MAP_LOCK(os) \
60 gcmkVERIFY_OK(gckOS_AcquireMutex( \
62 (os)->memoryMapLock, \
65 #define MEMORY_MAP_UNLOCK(os) \
66 gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
69 /******************************************************************************\
70 ******************************* Private Functions ******************************
71 \******************************************************************************/
77 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
78 return task_pid_vnr(current);
93 mdl = (PLINUX_MDL)kzalloc(sizeof(struct _LINUX_MDL), GFP_KERNEL | gcdNOWARN);
95 gcmkFOOTER_ARG("0x%X", mdl);
102 IN PLINUX_MDL_MAP MdlMap
110 PLINUX_MDL_MAP mdlMap, next;
112 gcmkHEADER_ARG("Mdl=0x%X", Mdl);
114 /* Verify the arguments. */
115 gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
119 while (mdlMap != gcvNULL)
123 gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
134 static PLINUX_MDL_MAP
140 PLINUX_MDL_MAP mdlMap;
142 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
144 mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_KERNEL | gcdNOWARN);
145 if (mdlMap == gcvNULL)
151 mdlMap->pid = ProcessID;
152 mdlMap->vmaAddr = gcvNULL;
153 mdlMap->vma = gcvNULL;
156 mdlMap->next = Mdl->maps;
159 gcmkFOOTER_ARG("0x%X", mdlMap);
166 IN PLINUX_MDL_MAP MdlMap
169 PLINUX_MDL_MAP prevMdlMap;
171 gcmkHEADER_ARG("Mdl=0x%X MdlMap=0x%X", Mdl, MdlMap);
173 /* Verify the arguments. */
174 gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
175 gcmkASSERT(Mdl->maps != gcvNULL);
177 if (Mdl->maps == MdlMap)
179 Mdl->maps = MdlMap->next;
183 prevMdlMap = Mdl->maps;
185 while (prevMdlMap->next != MdlMap)
187 prevMdlMap = prevMdlMap->next;
189 gcmkASSERT(prevMdlMap != gcvNULL);
192 prevMdlMap->next = MdlMap->next;
201 extern PLINUX_MDL_MAP
207 PLINUX_MDL_MAP mdlMap;
209 gcmkHEADER_ARG("Mdl=0x%X ProcessID=%d", Mdl, ProcessID);
217 while (mdlMap != gcvNULL)
219 if (mdlMap->pid == ProcessID)
221 gcmkFOOTER_ARG("0x%X", mdlMap);
225 mdlMap = mdlMap->next;
232 /*******************************************************************************
233 ** Integer Id Management.
237 IN gcsINTEGER_DB_PTR Database,
238 IN gctPOINTER KernelPointer,
245 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0)
246 idr_preload(GFP_KERNEL | gcdNOWARN);
248 spin_lock(&Database->lock);
250 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
252 result = idr_alloc(&Database->idr, KernelPointer, next, 0, GFP_ATOMIC);
254 /* ID allocated should not be 0. */
255 gcmkASSERT(result != 0);
259 Database->curr = *Id = result;
262 spin_unlock(&Database->lock);
268 return gcvSTATUS_OUT_OF_RESOURCES;
272 if (idr_pre_get(&Database->idr, GFP_KERNEL | gcdNOWARN) == 0)
274 return gcvSTATUS_OUT_OF_MEMORY;
277 spin_lock(&Database->lock);
279 next = (Database->curr + 1 <= 0) ? 1 : Database->curr + 1;
281 /* Try to get a id greater than 0. */
282 result = idr_get_new_above(&Database->idr, KernelPointer, next, Id);
286 Database->curr = *Id;
289 spin_unlock(&Database->lock);
291 if (result == -EAGAIN)
298 return gcvSTATUS_OUT_OF_RESOURCES;
307 IN gcsINTEGER_DB_PTR Database,
309 OUT gctPOINTER * KernelPointer
314 spin_lock(&Database->lock);
316 pointer = idr_find(&Database->idr, Id);
318 spin_unlock(&Database->lock);
322 *KernelPointer = pointer;
328 gcvLEVEL_ERROR, gcvZONE_OS,
329 "%s(%d) Id = %d is not found",
330 __FUNCTION__, __LINE__, Id);
332 return gcvSTATUS_NOT_FOUND;
338 IN gcsINTEGER_DB_PTR Database,
342 spin_lock(&Database->lock);
344 idr_remove(&Database->idr, Id);
346 spin_unlock(&Database->lock);
352 _QueryProcessPageTable(
353 IN gctPOINTER Logical,
354 OUT gctUINT32 * Address
358 gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
366 return gcvSTATUS_NOT_FOUND;
369 pgd = pgd_offset(current->mm, logical);
370 if (pgd_none(*pgd) || pgd_bad(*pgd))
372 return gcvSTATUS_NOT_FOUND;
375 pud = pud_offset(pgd, logical);
376 if (pud_none(*pud) || pud_bad(*pud))
378 return gcvSTATUS_NOT_FOUND;
381 pmd = pmd_offset(pud, logical);
382 if (pmd_none(*pmd) || pmd_bad(*pmd))
384 return gcvSTATUS_NOT_FOUND;
387 pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
390 return gcvSTATUS_NOT_FOUND;
393 if (!pte_present(*pte))
395 pte_unmap_unlock(pte, lock);
396 return gcvSTATUS_NOT_FOUND;
399 *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
400 pte_unmap_unlock(pte, lock);
405 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED && defined(CONFIG_OUTER_CACHE)
406 static inline gceSTATUS
408 gceCACHEOPERATION Type,
416 outer_clean_range(Start, End);
418 case gcvCACHE_INVALIDATE:
419 outer_inv_range(Start, End);
422 outer_flush_range(Start, End);
425 return gcvSTATUS_INVALID_ARGUMENT;
431 #if gcdENABLE_OUTER_CACHE_PATCH
432 /*******************************************************************************
435 ** Handle the outer cache for the specified addresses.
440 ** Pointer to gckOS object.
442 ** gctPOINTER Physical
443 ** Physical address to flush.
445 ** gctPOINTER Logical
446 ** Logical address to flush.
449 ** Size of the address range in bytes to flush.
451 ** gceOUTERCACHE_OPERATION Type
452 ** Operation need to be execute.
457 IN gctUINT32 Physical,
458 IN gctPOINTER Logical,
460 IN gceCACHEOPERATION Type
466 gctUINT32 offset, bytes, left;
468 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu",
471 if (Physical != gcvINVALID_ADDRESS)
473 /* Non paged memory or gcvPOOL_USER surface */
474 paddr = (unsigned long) Physical;
475 gcmkONERROR(outer_func(Type, paddr, paddr + Bytes));
479 /* Non contiguous virtual memory */
485 /* Handle (part of) current page. */
486 offset = (gctUINTPTR_T)vaddr & ~PAGE_MASK;
488 bytes = gcmMIN(left, PAGE_SIZE - offset);
490 gcmkONERROR(_QueryProcessPageTable(vaddr, (gctUINT32*)&paddr));
491 gcmkONERROR(outer_func(Type, paddr, paddr + bytes));
493 vaddr = (gctUINT8_PTR)vaddr + bytes;
505 /* Return the status. */
521 /* Check external clock state. */
522 if (Os->clockStates[Core] == gcvFALSE)
524 gcmkPRINT("[galcore]: %s(%d) External clock off", __FUNCTION__, __LINE__);
528 /* Check internal clock state. */
535 if (Core == gcvCORE_MAJOR)
537 data = readl((gctUINT8 *)Os->device->registerBases[gcvCORE_3D_0_ID] + 0x0);
542 data = readl((gctUINT8 *)Os->device->registerBases[Core] + 0x0);
545 if ((data & 0x3) == 0x3)
547 gcmkPRINT("[galcore]: %s(%d) Internal clock off", __FUNCTION__, __LINE__);
559 gcsPLATFORM * platform;
561 gcmkHEADER_ARG("Os=0x%X", Os);
562 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
564 platform = Os->device->platform;
566 if (platform && platform->ops->shrinkMemory)
568 platform->ops->shrinkMemory(platform);
573 return gcvSTATUS_NOT_SUPPORTED;
580 /*******************************************************************************
584 ** Construct a new gckOS object.
588 ** gctPOINTER Context
589 ** Pointer to the gckGALDEVICE class.
594 ** Pointer to a variable that will hold the pointer to the gckOS object.
598 IN gctPOINTER Context,
606 gcmkHEADER_ARG("Context=0x%X", Context);
608 /* Verify the arguments. */
609 gcmkVERIFY_ARGUMENT(Os != gcvNULL);
611 /* Allocate the gckOS object. */
612 os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_KERNEL | gcdNOWARN);
617 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
618 return gcvSTATUS_OUT_OF_MEMORY;
621 /* Zero the memory. */
622 gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
624 /* Initialize the gckOS object. */
625 os->object.type = gcvOBJ_OS;
627 /* Set device device. */
628 os->device = Context;
630 /* Set allocateCount to 0, gckOS_Allocate has not been used yet. */
631 atomic_set(&os->allocateCount, 0);
633 /* Initialize the memory lock. */
634 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
635 gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
637 /* Create debug lock mutex. */
638 gcmkONERROR(gckOS_CreateMutex(os, &os->debugLock));
640 os->mdlHead = os->mdlTail = gcvNULL;
642 /* Get the kernel process ID. */
643 gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
646 * Initialize the signal manager.
649 /* Initialize mutex. */
650 gcmkONERROR(gckOS_CreateMutex(os, &os->signalMutex));
652 /* Initialize signal id database lock. */
653 spin_lock_init(&os->signalDB.lock);
655 /* Initialize signal id database. */
656 idr_init(&os->signalDB.idr);
658 #if gcdANDROID_NATIVE_FENCE_SYNC
660 * Initialize the sync point manager.
663 /* Initialize mutex. */
664 gcmkONERROR(gckOS_CreateMutex(os, &os->syncPointMutex));
666 /* Initialize sync point id database lock. */
667 spin_lock_init(&os->syncPointDB.lock);
669 /* Initialize sync point id database. */
670 idr_init(&os->syncPointDB.idr);
673 /* Create a workqueue for os timer. */
674 os->workqueue = create_singlethread_workqueue("galcore workqueue");
676 if (os->workqueue == gcvNULL)
679 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
682 os->paddingPage = alloc_page(GFP_KERNEL | __GFP_HIGHMEM | gcdNOWARN);
683 if (os->paddingPage == gcvNULL)
686 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
690 SetPageReserved(os->paddingPage);
693 for (i = 0; i < gcdMAX_GPU_COUNT; i++)
695 mutex_init(&os->registerAccessLocks[i]);
698 gckOS_ImportAllocators(os);
700 #ifdef CONFIG_IOMMU_SUPPORT
701 if (((gckGALDEVICE)(os->device))->mmu == gcvFALSE)
703 /* Only use IOMMU when internal MMU is not enabled. */
704 status = gckIOMMU_Construct(os, &os->iommu);
706 if (gcmIS_ERROR(status))
709 gcvLEVEL_INFO, gcvZONE_OS,
710 "%s(%d): Fail to setup IOMMU",
711 __FUNCTION__, __LINE__
717 /* Return pointer to the gckOS object. */
721 gcmkFOOTER_ARG("*Os=0x%X", *Os);
726 #if gcdANDROID_NATIVE_FENCE_SYNC
727 if (os->syncPointMutex != gcvNULL)
730 gckOS_DeleteMutex(os, os->syncPointMutex));
734 if (os->signalMutex != gcvNULL)
737 gckOS_DeleteMutex(os, os->signalMutex));
740 if (os->memoryMapLock != gcvNULL)
743 gckOS_DeleteMutex(os, os->memoryMapLock));
746 if (os->memoryLock != gcvNULL)
749 gckOS_DeleteMutex(os, os->memoryLock));
752 if (os->debugLock != gcvNULL)
755 gckOS_DeleteMutex(os, os->debugLock));
758 if (os->workqueue != gcvNULL)
760 destroy_workqueue(os->workqueue);
765 /* Return the error. */
770 /*******************************************************************************
774 ** Destroy an gckOS object.
779 ** Pointer to an gckOS object that needs to be destroyed.
790 gcmkHEADER_ARG("Os=0x%X", Os);
792 /* Verify the arguments. */
793 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
795 if (Os->paddingPage != gcvNULL)
797 ClearPageReserved(Os->paddingPage);
798 __free_page(Os->paddingPage);
799 Os->paddingPage = gcvNULL;
802 #if gcdANDROID_NATIVE_FENCE_SYNC
804 * Destroy the sync point manager.
807 /* Destroy the mutex. */
808 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->syncPointMutex));
812 * Destroy the signal manager.
815 /* Destroy the mutex. */
816 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->signalMutex));
818 /* Destroy the memory lock. */
819 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryMapLock));
820 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->memoryLock));
822 /* Destroy debug lock mutex. */
823 gcmkVERIFY_OK(gckOS_DeleteMutex(Os, Os->debugLock));
825 /* Wait for all works done. */
826 flush_workqueue(Os->workqueue);
828 /* Destory work queue. */
829 destroy_workqueue(Os->workqueue);
831 gckOS_FreeAllocators(Os);
833 #ifdef CONFIG_IOMMU_SUPPORT
836 gckIOMMU_Destory(Os, Os->iommu);
840 /* Flush the debug cache. */
843 /* Mark the gckOS object as unknown. */
844 Os->object.type = gcvOBJ_UNKNOWN;
847 /* Free the gckOS object. */
856 gckOS_CreateKernelVirtualMapping(
858 IN gctPHYS_ADDR Physical,
860 OUT gctPOINTER * Logical,
861 OUT gctSIZE_T * PageCount
865 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
866 gckALLOCATOR allocator = mdl->allocator;
870 *PageCount = mdl->numPages;
872 gcmkONERROR(allocator->ops->MapKernel(allocator, mdl, Logical));
883 gckOS_DestroyKernelVirtualMapping(
885 IN gctPHYS_ADDR Physical,
887 IN gctPOINTER Logical
890 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
891 gckALLOCATOR allocator = mdl->allocator;
895 allocator->ops->UnmapKernel(allocator, mdl, Logical);
902 gckOS_CreateUserVirtualMapping(
904 IN gctPHYS_ADDR Physical,
906 OUT gctPOINTER * Logical,
907 OUT gctSIZE_T * PageCount
910 return gckOS_LockPages(Os, Physical, Bytes, gcvFALSE, Logical, PageCount);
914 gckOS_DestroyUserVirtualMapping(
916 IN gctPHYS_ADDR Physical,
918 IN gctPOINTER Logical
921 return gckOS_UnlockPages(Os, Physical, Bytes, Logical);
924 /*******************************************************************************
933 ** Pointer to an gckOS object.
936 ** Number of bytes to allocate.
940 ** gctPOINTER * Memory
941 ** Pointer to a variable that will hold the allocated memory location.
947 OUT gctPOINTER * Memory
952 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
954 /* Verify the arguments. */
955 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
956 gcmkVERIFY_ARGUMENT(Bytes > 0);
957 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
959 gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
962 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
966 /* Return the status. */
971 /*******************************************************************************
975 ** Free allocated memory.
980 ** Pointer to an gckOS object.
983 ** Pointer to memory allocation to free.
997 gcmkHEADER_ARG("Os=0x%X Memory=0x%X", Os, Memory);
999 /* Verify the arguments. */
1000 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1001 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1003 gcmkONERROR(gckOS_FreeMemory(Os, Memory));
1007 return gcvSTATUS_OK;
1010 /* Return the status. */
1015 /*******************************************************************************
1017 ** gckOS_AllocateMemory
1019 ** Allocate memory wrapper.
1024 ** Number of bytes to allocate.
1028 ** gctPOINTER * Memory
1029 ** Pointer to a variable that will hold the allocated memory location.
1032 gckOS_AllocateMemory(
1035 OUT gctPOINTER * Memory
1041 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
1043 /* Verify the arguments. */
1044 gcmkVERIFY_ARGUMENT(Bytes > 0);
1045 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1047 if (Bytes > PAGE_SIZE)
1049 memory = (gctPOINTER) vmalloc(Bytes);
1053 memory = (gctPOINTER) kmalloc(Bytes, GFP_KERNEL | gcdNOWARN);
1056 if (memory == gcvNULL)
1058 /* Out of memory. */
1059 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1062 /* Increase count. */
1063 atomic_inc(&Os->allocateCount);
1065 /* Return pointer to the memory allocation. */
1069 gcmkFOOTER_ARG("*Memory=0x%X", *Memory);
1070 return gcvSTATUS_OK;
1073 /* Return the status. */
1078 /*******************************************************************************
1082 ** Free allocated memory wrapper.
1086 ** gctPOINTER Memory
1087 ** Pointer to memory allocation to free.
1096 IN gctPOINTER Memory
1099 gcmkHEADER_ARG("Memory=0x%X", Memory);
1101 /* Verify the arguments. */
1102 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
1104 /* Free the memory from the OS pool. */
1105 if (is_vmalloc_addr(Memory))
1114 /* Decrease count. */
1115 atomic_dec(&Os->allocateCount);
1119 return gcvSTATUS_OK;
1122 /*******************************************************************************
1126 ** Map physical memory into the current process.
1131 ** Pointer to an gckOS object.
1133 ** gctPHYS_ADDR Physical
1134 ** Start of physical address memory.
1137 ** Number of bytes to map.
1141 ** gctPOINTER * Memory
1142 ** Pointer to a variable that will hold the logical address of the
1148 IN gctPHYS_ADDR Physical,
1150 OUT gctPOINTER * Logical
1153 PLINUX_MDL_MAP mdlMap;
1154 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1156 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
1158 /* Verify the arguments. */
1159 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1160 gcmkVERIFY_ARGUMENT(Physical != 0);
1161 gcmkVERIFY_ARGUMENT(Bytes > 0);
1162 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1166 mdlMap = FindMdlMap(mdl, _GetProcessID());
1168 if (mdlMap == gcvNULL)
1170 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1172 if (mdlMap == gcvNULL)
1176 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1177 return gcvSTATUS_OUT_OF_MEMORY;
1181 if (mdlMap->vmaAddr == gcvNULL)
1183 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1184 mdlMap->vmaAddr = (char *)vm_mmap(gcvNULL,
1186 mdl->numPages * PAGE_SIZE,
1187 PROT_READ | PROT_WRITE,
1191 down_write(¤t->mm->mmap_sem);
1193 mdlMap->vmaAddr = (char *)do_mmap_pgoff(gcvNULL,
1195 mdl->numPages * PAGE_SIZE,
1196 PROT_READ | PROT_WRITE,
1200 up_write(¤t->mm->mmap_sem);
1203 if (IS_ERR(mdlMap->vmaAddr))
1207 "%s(%d): do_mmap_pgoff error",
1208 __FUNCTION__, __LINE__
1213 "%s(%d): mdl->numPages: %d mdl->vmaAddr: 0x%X",
1214 __FUNCTION__, __LINE__,
1219 mdlMap->vmaAddr = gcvNULL;
1223 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
1224 return gcvSTATUS_OUT_OF_MEMORY;
1227 down_write(¤t->mm->mmap_sem);
1229 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1235 "%s(%d): find_vma error.",
1236 __FUNCTION__, __LINE__
1239 mdlMap->vmaAddr = gcvNULL;
1241 up_write(¤t->mm->mmap_sem);
1245 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1246 return gcvSTATUS_OUT_OF_RESOURCES;
1249 #ifndef NO_DMA_COHERENT
1250 if (dma_mmap_writecombine(gcvNULL,
1254 mdl->numPages * PAGE_SIZE) < 0)
1256 up_write(¤t->mm->mmap_sem);
1260 "%s(%d): dma_mmap_coherent error.",
1261 __FUNCTION__, __LINE__
1264 mdlMap->vmaAddr = gcvNULL;
1268 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1269 return gcvSTATUS_OUT_OF_RESOURCES;
1272 #if !gcdPAGED_MEMORY_CACHEABLE
1273 mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1274 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1276 mdlMap->vma->vm_pgoff = 0;
1278 if (remap_pfn_range(mdlMap->vma,
1279 mdlMap->vma->vm_start,
1280 mdl->dmaHandle >> PAGE_SHIFT,
1281 mdl->numPages*PAGE_SIZE,
1282 mdlMap->vma->vm_page_prot) < 0)
1284 up_write(¤t->mm->mmap_sem);
1288 "%s(%d): remap_pfn_range error.",
1289 __FUNCTION__, __LINE__
1292 mdlMap->vmaAddr = gcvNULL;
1296 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
1297 return gcvSTATUS_OUT_OF_RESOURCES;
1301 up_write(¤t->mm->mmap_sem);
1306 *Logical = mdlMap->vmaAddr;
1308 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
1309 return gcvSTATUS_OK;
1312 /*******************************************************************************
1314 ** gckOS_UnmapMemory
1316 ** Unmap physical memory out of the current process.
1321 ** Pointer to an gckOS object.
1323 ** gctPHYS_ADDR Physical
1324 ** Start of physical address memory.
1327 ** Number of bytes to unmap.
1329 ** gctPOINTER Memory
1330 ** Pointer to a previously mapped memory region.
1339 IN gctPHYS_ADDR Physical,
1341 IN gctPOINTER Logical
1344 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1345 Os, Physical, Bytes, Logical);
1347 /* Verify the arguments. */
1348 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1349 gcmkVERIFY_ARGUMENT(Physical != 0);
1350 gcmkVERIFY_ARGUMENT(Bytes > 0);
1351 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1353 gckOS_UnmapMemoryEx(Os, Physical, Bytes, Logical, _GetProcessID());
1357 return gcvSTATUS_OK;
1361 /*******************************************************************************
1363 ** gckOS_UnmapMemoryEx
1365 ** Unmap physical memory in the specified process.
1370 ** Pointer to an gckOS object.
1372 ** gctPHYS_ADDR Physical
1373 ** Start of physical address memory.
1376 ** Number of bytes to unmap.
1378 ** gctPOINTER Memory
1379 ** Pointer to a previously mapped memory region.
1382 ** Pid of the process that opened the device and mapped this memory.
1389 gckOS_UnmapMemoryEx(
1391 IN gctPHYS_ADDR Physical,
1393 IN gctPOINTER Logical,
1397 PLINUX_MDL_MAP mdlMap;
1398 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
1400 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X PID=%d",
1401 Os, Physical, Bytes, Logical, PID);
1403 /* Verify the arguments. */
1404 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1405 gcmkVERIFY_ARGUMENT(Physical != 0);
1406 gcmkVERIFY_ARGUMENT(Bytes > 0);
1407 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1408 gcmkVERIFY_ARGUMENT(PID != 0);
1414 mdlMap = FindMdlMap(mdl, PID);
1416 if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1420 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
1421 return gcvSTATUS_INVALID_ARGUMENT;
1424 _UnmapUserLogical(mdlMap->vmaAddr, mdl->numPages * PAGE_SIZE);
1426 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1433 return gcvSTATUS_OK;
1436 /*******************************************************************************
1438 ** gckOS_UnmapUserLogical
1440 ** Unmap user logical memory out of physical memory.
1445 ** Pointer to an gckOS object.
1447 ** gctPHYS_ADDR Physical
1448 ** Start of physical address memory.
1451 ** Number of bytes to unmap.
1453 ** gctPOINTER Memory
1454 ** Pointer to a previously mapped memory region.
1461 gckOS_UnmapUserLogical(
1463 IN gctPHYS_ADDR Physical,
1465 IN gctPOINTER Logical
1468 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu Logical=0x%X",
1469 Os, Physical, Bytes, Logical);
1471 /* Verify the arguments. */
1472 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1473 gcmkVERIFY_ARGUMENT(Physical != 0);
1474 gcmkVERIFY_ARGUMENT(Bytes > 0);
1475 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1477 gckOS_UnmapMemory(Os, Physical, Bytes, Logical);
1481 return gcvSTATUS_OK;
1485 /*******************************************************************************
1487 ** gckOS_AllocateNonPagedMemory
1489 ** Allocate a number of pages from non-paged memory.
1494 ** Pointer to an gckOS object.
1496 ** gctBOOL InUserSpace
1497 ** gcvTRUE if the pages need to be mapped into user space.
1499 ** gctSIZE_T * Bytes
1500 ** Pointer to a variable that holds the number of bytes to allocate.
1504 ** gctSIZE_T * Bytes
1505 ** Pointer to a variable that hold the number of bytes allocated.
1507 ** gctPHYS_ADDR * Physical
1508 ** Pointer to a variable that will hold the physical address of the
1511 ** gctPOINTER * Logical
1512 ** Pointer to a variable that will hold the logical address of the
1516 gckOS_AllocateNonPagedMemory(
1518 IN gctBOOL InUserSpace,
1519 IN OUT gctSIZE_T * Bytes,
1520 OUT gctPHYS_ADDR * Physical,
1521 OUT gctPOINTER * Logical
1526 PLINUX_MDL mdl = gcvNULL;
1527 PLINUX_MDL_MAP mdlMap = gcvNULL;
1530 #ifdef NO_DMA_COHERENT
1535 gctBOOL locked = gcvFALSE;
1538 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
1539 Os, InUserSpace, gcmOPT_VALUE(Bytes));
1541 /* Verify the arguments. */
1542 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1543 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
1544 gcmkVERIFY_ARGUMENT(*Bytes > 0);
1545 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
1546 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1548 /* Align number of bytes to page size. */
1549 bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1551 /* Get total number of pages.. */
1552 numPages = GetPageCount(bytes, 0);
1554 /* Allocate mdl+vector structure */
1558 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1562 mdl->numPages = numPages;
1567 #ifndef NO_DMA_COHERENT
1569 addr = dma_alloc_coherent(gcvNULL,
1571 addr = dma_alloc_writecombine(gcvNULL,
1573 mdl->numPages * PAGE_SIZE,
1575 GFP_KERNEL | gcdNOWARN);
1577 size = mdl->numPages * PAGE_SIZE;
1578 order = get_order(size);
1580 page = alloc_pages(GFP_KERNEL | gcdNOWARN, order);
1582 if (page == gcvNULL)
1584 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1587 vaddr = (gctPOINTER)page_address(page);
1588 mdl->contiguous = gcvTRUE;
1589 mdl->u.contiguousPages = page;
1590 addr = _CreateKernelVirtualMapping(mdl);
1591 mdl->dmaHandle = virt_to_phys(vaddr);
1594 /* Trigger a page fault. */
1595 memset(addr, 0, numPages * PAGE_SIZE);
1597 #if !defined(CONFIG_PPC)
1598 /* Cache invalidate. */
1599 dma_sync_single_for_device(
1608 SetPageReserved(virt_to_page(vaddr));
1615 if (addr == gcvNULL)
1617 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1620 kernel = Os->device->kernels[gcvCORE_MAJOR] != gcvNULL ?
1621 Os->device->kernels[gcvCORE_MAJOR] : Os->device->kernels[gcvCORE_2D];
1622 if (((Os->device->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000)) &&
1623 kernel->hardware->mmuVersion == 0)
1625 mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1626 | (Os->device->baseAddress & 0x80000000);
1631 /* Return allocated memory. */
1633 *Physical = (gctPHYS_ADDR) mdl;
1637 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
1639 if (mdlMap == gcvNULL)
1641 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1644 /* Only after mmap this will be valid. */
1646 /* We need to map this to user space. */
1647 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
1648 mdlMap->vmaAddr = (gctSTRING) vm_mmap(gcvNULL,
1650 mdl->numPages * PAGE_SIZE,
1651 PROT_READ | PROT_WRITE,
1655 down_write(¤t->mm->mmap_sem);
1657 mdlMap->vmaAddr = (gctSTRING) do_mmap_pgoff(gcvNULL,
1659 mdl->numPages * PAGE_SIZE,
1660 PROT_READ | PROT_WRITE,
1664 up_write(¤t->mm->mmap_sem);
1667 if (IS_ERR(mdlMap->vmaAddr))
1670 gcvLEVEL_WARNING, gcvZONE_OS,
1671 "%s(%d): do_mmap_pgoff error",
1672 __FUNCTION__, __LINE__
1675 mdlMap->vmaAddr = gcvNULL;
1677 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
1680 down_write(¤t->mm->mmap_sem);
1682 mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1684 if (mdlMap->vma == gcvNULL)
1687 gcvLEVEL_WARNING, gcvZONE_OS,
1688 "%s(%d): find_vma error",
1689 __FUNCTION__, __LINE__
1692 up_write(¤t->mm->mmap_sem);
1694 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1697 #ifndef NO_DMA_COHERENT
1698 if (dma_mmap_coherent(gcvNULL,
1702 mdl->numPages * PAGE_SIZE) < 0)
1705 gcvLEVEL_WARNING, gcvZONE_OS,
1706 "%s(%d): dma_mmap_coherent error",
1707 __FUNCTION__, __LINE__
1710 up_write(¤t->mm->mmap_sem);
1712 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1716 mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1718 mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1719 mdlMap->vma->vm_pgoff = 0;
1721 if (remap_pfn_range(mdlMap->vma,
1722 mdlMap->vma->vm_start,
1723 mdl->dmaHandle >> PAGE_SHIFT,
1724 mdl->numPages * PAGE_SIZE,
1725 mdlMap->vma->vm_page_prot))
1728 gcvLEVEL_WARNING, gcvZONE_OS,
1729 "%s(%d): remap_pfn_range error",
1730 __FUNCTION__, __LINE__
1733 up_write(¤t->mm->mmap_sem);
1735 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
1737 #endif /* NO_DMA_COHERENT */
1739 up_write(¤t->mm->mmap_sem);
1741 *Logical = mdlMap->vmaAddr;
1746 *Logical = (gctPOINTER)mdl->kaddr;
1748 *Logical = (gctPOINTER)mdl->addr;
1753 * Add this to a global list.
1754 * Will be used by get physical address
1755 * and mapuser pointer functions.
1760 /* Initialize the queue. */
1761 Os->mdlHead = Os->mdlTail = mdl;
1765 /* Add to the tail. */
1766 mdl->prev = Os->mdlTail;
1767 Os->mdlTail->next = mdl;
1774 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
1775 *Bytes, *Physical, *Logical);
1776 return gcvSTATUS_OK;
1779 if (mdlMap != gcvNULL)
1781 /* Free LINUX_MDL_MAP. */
1782 gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1787 /* Free LINUX_MDL. */
1788 gcmkVERIFY_OK(_DestroyMdl(mdl));
1790 *Physical = gcvNULL;
1795 /* Unlock memory. */
1799 /* Return the status. */
1804 /*******************************************************************************
1806 ** gckOS_FreeNonPagedMemory
1808 ** Free previously allocated and mapped pages from non-paged memory.
1813 ** Pointer to an gckOS object.
1816 ** Number of bytes allocated.
1818 ** gctPHYS_ADDR Physical
1819 ** Physical address of the allocated memory.
1821 ** gctPOINTER Logical
1822 ** Logical address of the allocated memory.
1828 gceSTATUS gckOS_FreeNonPagedMemory(
1831 IN gctPHYS_ADDR Physical,
1832 IN gctPOINTER Logical
1836 PLINUX_MDL_MAP mdlMap;
1837 #ifdef NO_DMA_COHERENT
1840 #endif /* NO_DMA_COHERENT */
1842 gcmkHEADER_ARG("Os=0x%X Bytes=%lu Physical=0x%X Logical=0x%X",
1843 Os, Bytes, Physical, Logical);
1845 /* Verify the arguments. */
1846 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1847 gcmkVERIFY_ARGUMENT(Bytes > 0);
1848 gcmkVERIFY_ARGUMENT(Physical != 0);
1849 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1851 /* Convert physical address into a pointer to a MDL. */
1852 mdl = (PLINUX_MDL) Physical;
1856 #ifndef NO_DMA_COHERENT
1858 dma_free_coherent(gcvNULL,
1860 dma_free_writecombine(gcvNULL,
1862 mdl->numPages * PAGE_SIZE,
1866 size = mdl->numPages * PAGE_SIZE;
1871 ClearPageReserved(virt_to_page(vaddr));
1877 free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
1879 _DestoryKernelVirtualMapping(mdl->addr);
1880 #endif /* NO_DMA_COHERENT */
1884 while (mdlMap != gcvNULL)
1886 /* No mapped memory exists when free nonpaged memory */
1887 gcmkASSERT(mdlMap->vmaAddr == gcvNULL);
1889 mdlMap = mdlMap->next;
1892 /* Remove the node from global list.. */
1893 if (mdl == Os->mdlHead)
1895 if ((Os->mdlHead = mdl->next) == gcvNULL)
1897 Os->mdlTail = gcvNULL;
1902 mdl->prev->next = mdl->next;
1903 if (mdl == Os->mdlTail)
1905 Os->mdlTail = mdl->prev;
1909 mdl->next->prev = mdl->prev;
1915 gcmkVERIFY_OK(_DestroyMdl(mdl));
1919 return gcvSTATUS_OK;
1922 /*******************************************************************************
1924 ** gckOS_ReadRegister
1926 ** Read data from a register.
1931 ** Pointer to an gckOS object.
1933 ** gctUINT32 Address
1934 ** Address of register.
1939 ** Pointer to a variable that receives the data read from the register.
1944 IN gctUINT32 Address,
1945 OUT gctUINT32 * Data
1948 return gckOS_ReadRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
1952 gckOS_ReadRegisterEx(
1955 IN gctUINT32 Address,
1956 OUT gctUINT32 * Data
1959 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X", Os, Core, Address);
1961 /* Verify the arguments. */
1962 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1964 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
1966 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
1968 if (!in_interrupt())
1970 mutex_lock(&Os->registerAccessLocks[Core]);
1973 BUG_ON(!_AllowAccess(Os, Core, Address));
1976 if (Core == gcvCORE_MAJOR)
1978 *Data = readl((gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_0_ID] + Address);
1983 *Data = readl((gctUINT8 *)Os->device->registerBases[Core] + Address);
1986 if (!in_interrupt())
1988 mutex_unlock(&Os->registerAccessLocks[Core]);
1992 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
1993 return gcvSTATUS_OK;
1998 gckOS_ReadRegisterByCoreId(
2001 IN gctUINT32 CoreId,
2002 IN gctUINT32 Address,
2003 OUT gctUINT32 * Data
2006 gcmkHEADER_ARG("Os=0x%X Core=%d CoreId=%d Address=0x%X",
2007 Os, Core, CoreId, Address);
2009 /* Verify the arguments. */
2010 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2011 gcmkVERIFY_ARGUMENT(Data != gcvNULL);
2013 *Data = readl((gctUINT8 *)Os->device->registerBase3D[CoreId] + Address);
2016 gcmkFOOTER_ARG("*Data=0x%08x", *Data);
2017 return gcvSTATUS_OK;
2021 /*******************************************************************************
2023 ** gckOS_WriteRegister
2025 ** Write data to a register.
2030 ** Pointer to an gckOS object.
2032 ** gctUINT32 Address
2033 ** Address of register.
2036 ** Data for register.
2043 gckOS_WriteRegister(
2045 IN gctUINT32 Address,
2049 return gckOS_WriteRegisterEx(Os, gcvCORE_MAJOR, Address, Data);
2053 gckOS_WriteRegisterEx(
2056 IN gctUINT32 Address,
2060 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%X Data=0x%08x", Os, Core, Address, Data);
2063 gcmkVERIFY_ARGUMENT(Address < Os->device->requestedRegisterMemSizes[Core]);
2066 if (!in_interrupt())
2068 mutex_lock(&Os->registerAccessLocks[Core]);
2071 BUG_ON(!_AllowAccess(Os, Core, Address));
2074 if (Core == gcvCORE_MAJOR)
2076 writel(Data, (gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_0_ID] + Address);
2077 #if gcdMULTI_GPU > 1
2078 writel(Data, (gctUINT8 *)Os->device->registerBase3D[gcvCORE_3D_1_ID] + Address);
2084 writel(Data, (gctUINT8 *)Os->device->registerBases[Core] + Address);
2087 if (!in_interrupt())
2089 mutex_unlock(&Os->registerAccessLocks[Core]);
2094 return gcvSTATUS_OK;
2099 gckOS_WriteRegisterByCoreId(
2102 IN gctUINT32 CoreId,
2103 IN gctUINT32 Address,
2107 gcmkHEADER_ARG("Os=0x%X Core=%d CoreId=%d Address=0x%X Data=0x%08x",
2108 Os, Core, CoreId, Address, Data);
2110 writel(Data, (gctUINT8 *)Os->device->registerBase3D[CoreId] + Address);
2114 return gcvSTATUS_OK;
2118 /*******************************************************************************
2120 ** gckOS_GetPageSize
2122 ** Get the system's page size.
2127 ** Pointer to an gckOS object.
2131 ** gctSIZE_T * PageSize
2132 ** Pointer to a variable that will receive the system's page size.
2134 gceSTATUS gckOS_GetPageSize(
2136 OUT gctSIZE_T * PageSize
2139 gcmkHEADER_ARG("Os=0x%X", Os);
2141 /* Verify the arguments. */
2142 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2143 gcmkVERIFY_ARGUMENT(PageSize != gcvNULL);
2145 /* Return the page size. */
2146 *PageSize = (gctSIZE_T) PAGE_SIZE;
2149 gcmkFOOTER_ARG("*PageSize", *PageSize);
2150 return gcvSTATUS_OK;
2153 /*******************************************************************************
2155 ** gckOS_GetPhysicalAddress
2157 ** Get the physical system address of a corresponding virtual address.
2162 ** Pointer to an gckOS object.
2164 ** gctPOINTER Logical
2169 ** gctUINT32 * Address
2170 ** Poinetr to a variable that receives the 32-bit physical adress.
2173 gckOS_GetPhysicalAddress(
2175 IN gctPOINTER Logical,
2176 OUT gctUINT32 * Address
2180 gctUINT32 processID;
2182 gcmkHEADER_ARG("Os=0x%X Logical=0x%X", Os, Logical);
2184 /* Verify the arguments. */
2185 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2186 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2188 /* Query page table of current process first. */
2189 status = _QueryProcessPageTable(Logical, Address);
2191 if (gcmIS_ERROR(status))
2193 /* Get current process ID. */
2194 processID = _GetProcessID();
2196 /* Route through other function. */
2198 gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
2201 gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
2204 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2205 return gcvSTATUS_OK;
2208 /* Return the status. */
2213 /*******************************************************************************
2215 ** gckOS_UserLogicalToPhysical
2217 ** Get the physical system address of a corresponding user virtual address.
2222 ** Pointer to an gckOS object.
2224 ** gctPOINTER Logical
2229 ** gctUINT32 * Address
2230 ** Pointer to a variable that receives the 32-bit physical address.
2232 gceSTATUS gckOS_UserLogicalToPhysical(
2234 IN gctPOINTER Logical,
2235 OUT gctUINT32 * Address
2238 return gckOS_GetPhysicalAddress(Os, Logical, Address);
2245 IN gctUINT32 Physical,
2246 IN gctPOINTER Logical,
2251 gcsUSER_MAPPING_PTR map;
2253 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
2254 Os, Physical, Logical, Bytes);
2256 gcmkONERROR(gckOS_Allocate(Os,
2257 gcmSIZEOF(gcsUSER_MAPPING),
2258 (gctPOINTER *) &map));
2260 map->next = Os->userMap;
2261 map->physical = Physical - Os->device->baseAddress;
2262 map->logical = Logical;
2264 map->start = (gctINT8_PTR) Logical;
2265 map->end = map->start + Bytes;
2270 return gcvSTATUS_OK;
2278 gckOS_RemoveMapping(
2280 IN gctPOINTER Logical,
2285 gcsUSER_MAPPING_PTR map, prev;
2287 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2289 for (map = Os->userMap, prev = gcvNULL; map != gcvNULL; map = map->next)
2291 if ((map->logical == Logical)
2292 && (map->bytes == Bytes)
2303 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
2306 if (prev == gcvNULL)
2308 Os->userMap = map->next;
2312 prev->next = map->next;
2315 gcmkONERROR(gcmkOS_SAFE_FREE(Os, map));
2318 return gcvSTATUS_OK;
2327 _ConvertLogical2Physical(
2329 IN gctPOINTER Logical,
2330 IN gctUINT32 ProcessID,
2332 OUT gctUINT32_PTR Physical
2335 gctINT8_PTR base, vBase;
2338 gcsUSER_MAPPING_PTR userMap;
2341 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->kaddr;
2343 base = (Mdl == gcvNULL) ? gcvNULL : (gctINT8_PTR) Mdl->addr;
2346 /* Check for the logical address match. */
2347 if ((base != gcvNULL)
2348 && ((gctINT8_PTR) Logical >= base)
2349 && ((gctINT8_PTR) Logical < base + Mdl->numPages * PAGE_SIZE)
2352 offset = (gctINT8_PTR) Logical - base;
2354 if (Mdl->dmaHandle != 0)
2356 /* The memory was from coherent area. */
2357 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2359 else if (Mdl->pagedMem && !Mdl->contiguous)
2361 /* paged memory is not mapped to kernel space. */
2362 return gcvSTATUS_INVALID_ADDRESS;
2366 *Physical = gcmPTR2INT32(virt_to_phys(base)) + offset;
2369 return gcvSTATUS_OK;
2372 /* Walk user maps. */
2373 for (userMap = Os->userMap; userMap != gcvNULL; userMap = userMap->next)
2375 if (((gctINT8_PTR) Logical >= userMap->start)
2376 && ((gctINT8_PTR) Logical < userMap->end)
2379 *Physical = userMap->physical
2380 + (gctUINT32) ((gctINT8_PTR) Logical - userMap->start);
2382 return gcvSTATUS_OK;
2386 if (ProcessID != Os->kernelProcessID)
2388 map = FindMdlMap(Mdl, (gctINT) ProcessID);
2389 vBase = (map == gcvNULL) ? gcvNULL : (gctINT8_PTR) map->vmaAddr;
2391 /* Is the given address within that range. */
2392 if ((vBase != gcvNULL)
2393 && ((gctINT8_PTR) Logical >= vBase)
2394 && ((gctINT8_PTR) Logical < vBase + Mdl->numPages * PAGE_SIZE)
2397 offset = (gctINT8_PTR) Logical - vBase;
2399 if (Mdl->dmaHandle != 0)
2401 /* The memory was from coherent area. */
2402 *Physical = (gctUINT32) Mdl->dmaHandle + offset;
2404 else if (Mdl->pagedMem && !Mdl->contiguous)
2406 *Physical = _NonContiguousToPhys(Mdl->u.nonContiguousPages, offset/PAGE_SIZE);
2410 *Physical = page_to_phys(Mdl->u.contiguousPages) + offset;
2413 return gcvSTATUS_OK;
2417 /* Address not yet found. */
2418 return gcvSTATUS_INVALID_ADDRESS;
2421 /*******************************************************************************
2423 ** gckOS_GetPhysicalAddressProcess
2425 ** Get the physical system address of a corresponding virtual address for a
2431 ** Pointer to gckOS object.
2433 ** gctPOINTER Logical
2436 ** gctUINT32 ProcessID
2441 ** gctUINT32 * Address
2442 ** Poinetr to a variable that receives the 32-bit physical adress.
2445 gckOS_GetPhysicalAddressProcess(
2447 IN gctPOINTER Logical,
2448 IN gctUINT32 ProcessID,
2449 OUT gctUINT32 * Address
2454 gckALLOCATOR allocator = gcvNULL;
2455 gceSTATUS status = gcvSTATUS_INVALID_ADDRESS;
2457 gcmkHEADER_ARG("Os=0x%X Logical=0x%X ProcessID=%d", Os, Logical, ProcessID);
2459 /* Verify the arguments. */
2460 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2461 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
2465 /* First try the contiguous memory pool. */
2466 if (Os->device->contiguousMapped)
2468 base = (gctINT8_PTR) Os->device->contiguousBase;
2470 if (((gctINT8_PTR) Logical >= base)
2471 && ((gctINT8_PTR) Logical < base + Os->device->contiguousSize)
2474 /* Convert logical address into physical. */
2475 *Address = Os->device->contiguousVidMem->baseAddress
2476 + (gctINT8_PTR) Logical - base;
2477 status = gcvSTATUS_OK;
2482 /* Try the contiguous memory pool. */
2483 mdl = (PLINUX_MDL) Os->device->contiguousPhysical;
2484 status = _ConvertLogical2Physical(Os,
2491 if (gcmIS_ERROR(status))
2493 /* Walk all MDLs. */
2494 for (mdl = Os->mdlHead; mdl != gcvNULL; mdl = mdl->next)
2497 allocator = mdl->allocator;
2501 status = allocator->ops->LogicalToPhysical(
2511 status = _ConvertLogical2Physical(Os,
2518 if (gcmIS_SUCCESS(status))
2527 gcmkONERROR(status);
2530 gcmkFOOTER_ARG("*Address=0x%08x", *Address);
2531 return gcvSTATUS_OK;
2534 /* Return the status. */
2539 /*******************************************************************************
2541 ** gckOS_MapPhysical
2543 ** Map a physical address into kernel space.
2548 ** Pointer to an gckOS object.
2550 ** gctUINT32 Physical
2551 ** Physical address of the memory to map.
2554 ** Number of bytes to map.
2558 ** gctPOINTER * Logical
2559 ** Pointer to a variable that receives the base address of the mapped
2565 IN gctUINT32 Physical,
2567 OUT gctPOINTER * Logical
2572 gctUINT32 physical = Physical;
2574 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
2576 /* Verify the arguments. */
2577 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2578 gcmkVERIFY_ARGUMENT(Bytes > 0);
2579 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2583 /* Go through our mapping to see if we know this physical address already. */
2586 while (mdl != gcvNULL)
2588 if (mdl->dmaHandle != 0)
2590 if ((physical >= mdl->dmaHandle)
2591 && (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
2594 *Logical = mdl->addr + (physical - mdl->dmaHandle);
2606 struct page * page = pfn_to_page(physical >> PAGE_SHIFT);
2608 if (pfn_valid(page_to_pfn(page)))
2610 gctUINT32 offset = physical & ~PAGE_MASK;
2611 struct page ** pages;
2615 numPages = GetPageCount(PAGE_ALIGN(offset + Bytes), 0);
2617 pages = kmalloc(sizeof(struct page *) * numPages, GFP_KERNEL | gcdNOWARN);
2621 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
2622 return gcvSTATUS_OUT_OF_MEMORY;
2625 for (i = 0; i < numPages; i++)
2627 pages[i] = nth_page(page, i);
2630 logical = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
2634 if (logical == gcvNULL)
2637 gcvLEVEL_INFO, gcvZONE_OS,
2638 "%s(%d): Failed to vmap",
2639 __FUNCTION__, __LINE__
2642 /* Out of resources. */
2643 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2644 return gcvSTATUS_OUT_OF_RESOURCES;
2651 /* Map memory as cached memory. */
2652 request_mem_region(physical, Bytes, "MapRegion");
2653 logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
2655 if (logical == gcvNULL)
2658 gcvLEVEL_INFO, gcvZONE_OS,
2659 "%s(%d): Failed to ioremap",
2660 __FUNCTION__, __LINE__
2663 /* Out of resources. */
2664 gcmkFOOTER_ARG("status=%d", gcvSTATUS_OUT_OF_RESOURCES);
2665 return gcvSTATUS_OUT_OF_RESOURCES;
2669 /* Return pointer to mapped memory. */
2675 gcmkFOOTER_ARG("*Logical=0x%X", *Logical);
2676 return gcvSTATUS_OK;
2679 /*******************************************************************************
2681 ** gckOS_UnmapPhysical
2683 ** Unmap a previously mapped memory region from kernel memory.
2688 ** Pointer to an gckOS object.
2690 ** gctPOINTER Logical
2691 ** Pointer to the base address of the memory to unmap.
2694 ** Number of bytes to unmap.
2701 gckOS_UnmapPhysical(
2703 IN gctPOINTER Logical,
2709 gcmkHEADER_ARG("Os=0x%X Logical=0x%X Bytes=%lu", Os, Logical, Bytes);
2711 /* Verify the arguments. */
2712 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2713 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
2714 gcmkVERIFY_ARGUMENT(Bytes > 0);
2720 while (mdl != gcvNULL)
2722 if (mdl->addr != gcvNULL)
2724 if (Logical >= (gctPOINTER)mdl->addr
2725 && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2736 /* Unmap the memory. */
2737 vunmap((void *)((unsigned long)Logical & PAGE_MASK));
2744 return gcvSTATUS_OK;
2747 /*******************************************************************************
2749 ** gckOS_CreateMutex
2751 ** Create a new mutex.
2756 ** Pointer to an gckOS object.
2760 ** gctPOINTER * Mutex
2761 ** Pointer to a variable that will hold a pointer to the mutex.
2766 OUT gctPOINTER * Mutex
2771 gcmkHEADER_ARG("Os=0x%X", Os);
2773 /* Validate the arguments. */
2774 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2775 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2777 /* Allocate the mutex structure. */
2778 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(struct mutex), Mutex));
2780 /* Initialize the mutex. */
2783 /* Return status. */
2784 gcmkFOOTER_ARG("*Mutex=0x%X", *Mutex);
2785 return gcvSTATUS_OK;
2788 /* Return status. */
2793 /*******************************************************************************
2795 ** gckOS_DeleteMutex
2802 ** Pointer to an gckOS object.
2805 ** Pointer to the mute to be deleted.
2819 gcmkHEADER_ARG("Os=0x%X Mutex=0x%X", Os, Mutex);
2821 /* Validate the arguments. */
2822 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2823 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2825 /* Destroy the mutex. */
2826 mutex_destroy((struct mutex *)Mutex);
2828 /* Free the mutex structure. */
2829 gcmkONERROR(gckOS_Free(Os, Mutex));
2832 return gcvSTATUS_OK;
2835 /* Return status. */
2840 /*******************************************************************************
2842 ** gckOS_AcquireMutex
2849 ** Pointer to an gckOS object.
2852 ** Pointer to the mutex to be acquired.
2854 ** gctUINT32 Timeout
2855 ** Timeout value specified in milliseconds.
2856 ** Specify the value of gcvINFINITE to keep the thread suspended
2857 ** until the mutex has been acquired.
2866 IN gctPOINTER Mutex,
2867 IN gctUINT32 Timeout
2870 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x Timeout=%u", Os, Mutex, Timeout);
2872 /* Validate the arguments. */
2873 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2874 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2876 if (Timeout == gcvINFINITE)
2878 /* Lock the mutex. */
2883 return gcvSTATUS_OK;
2888 /* Try to acquire the mutex. */
2889 if (mutex_trylock(Mutex))
2893 return gcvSTATUS_OK;
2901 /* Wait for 1 millisecond. */
2902 gcmkVERIFY_OK(gckOS_Delay(Os, 1));
2906 gcmkFOOTER_ARG("status=%d", gcvSTATUS_TIMEOUT);
2907 return gcvSTATUS_TIMEOUT;
2910 /*******************************************************************************
2912 ** gckOS_ReleaseMutex
2914 ** Release an acquired mutex.
2919 ** Pointer to an gckOS object.
2922 ** Pointer to the mutex to be released.
2934 gcmkHEADER_ARG("Os=0x%X Mutex=0x%0x", Os, Mutex);
2936 /* Validate the arguments. */
2937 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2938 gcmkVERIFY_ARGUMENT(Mutex != gcvNULL);
2940 /* Release the mutex. */
2941 mutex_unlock(Mutex);
2945 return gcvSTATUS_OK;
2948 /*******************************************************************************
2950 ** gckOS_AtomicExchange
2952 ** Atomically exchange a pair of 32-bit values.
2957 ** Pointer to an gckOS object.
2959 ** IN OUT gctINT32_PTR Target
2960 ** Pointer to the 32-bit value to exchange.
2962 ** IN gctINT32 NewValue
2963 ** Specifies a new value for the 32-bit value pointed to by Target.
2965 ** OUT gctINT32_PTR OldValue
2966 ** The old value of the 32-bit value pointed to by Target.
2973 gckOS_AtomicExchange(
2975 IN OUT gctUINT32_PTR Target,
2976 IN gctUINT32 NewValue,
2977 OUT gctUINT32_PTR OldValue
2980 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=%u", Os, Target, NewValue);
2982 /* Verify the arguments. */
2983 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2984 gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
2986 /* Exchange the pair of 32-bit values. */
2987 *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
2990 gcmkFOOTER_ARG("*OldValue=%u", *OldValue);
2991 return gcvSTATUS_OK;
2994 /*******************************************************************************
2996 ** gckOS_AtomicExchangePtr
2998 ** Atomically exchange a pair of pointers.
3003 ** Pointer to an gckOS object.
3005 ** IN OUT gctPOINTER * Target
3006 ** Pointer to the 32-bit value to exchange.
3008 ** IN gctPOINTER NewValue
3009 ** Specifies a new value for the pointer pointed to by Target.
3011 ** OUT gctPOINTER * OldValue
3012 ** The old value of the pointer pointed to by Target.
3019 gckOS_AtomicExchangePtr(
3021 IN OUT gctPOINTER * Target,
3022 IN gctPOINTER NewValue,
3023 OUT gctPOINTER * OldValue
3026 gcmkHEADER_ARG("Os=0x%X Target=0x%X NewValue=0x%X", Os, Target, NewValue);
3028 /* Verify the arguments. */
3029 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3030 gcmkVERIFY_ARGUMENT(OldValue != gcvNULL);
3032 /* Exchange the pair of pointers. */
3033 *OldValue = (gctPOINTER)(gctUINTPTR_T) atomic_xchg((atomic_t *) Target, (int)(gctUINTPTR_T) NewValue);
3036 gcmkFOOTER_ARG("*OldValue=0x%X", *OldValue);
3037 return gcvSTATUS_OK;
3040 /*******************************************************************************
3042 ** gckOS_AtomicSetMask
3044 ** Atomically set mask to Atom
3047 ** IN OUT gctPOINTER Atom
3048 ** Pointer to the atom to set.
3050 ** IN gctUINT32 Mask
3063 gctUINT32 oval, nval;
3065 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3066 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3070 oval = atomic_read((atomic_t *) Atom);
3072 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3075 return gcvSTATUS_OK;
3078 /*******************************************************************************
3080 ** gckOS_AtomClearMask
3082 ** Atomically clear mask from Atom
3085 ** IN OUT gctPOINTER Atom
3086 ** Pointer to the atom to clear.
3088 ** IN gctUINT32 Mask
3096 gckOS_AtomClearMask(
3101 gctUINT32 oval, nval;
3103 gcmkHEADER_ARG("Atom=0x%0x", Atom);
3104 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3108 oval = atomic_read((atomic_t *) Atom);
3109 nval = oval & ~Mask;
3110 } while (atomic_cmpxchg((atomic_t *) Atom, oval, nval) != oval);
3113 return gcvSTATUS_OK;
3116 /*******************************************************************************
3118 ** gckOS_AtomConstruct
3125 ** Pointer to a gckOS object.
3129 ** gctPOINTER * Atom
3130 ** Pointer to a variable receiving the constructed atom.
3133 gckOS_AtomConstruct(
3135 OUT gctPOINTER * Atom
3140 gcmkHEADER_ARG("Os=0x%X", Os);
3142 /* Verify the arguments. */
3143 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3144 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3146 /* Allocate the atom. */
3147 gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
3149 /* Initialize the atom. */
3150 atomic_set((atomic_t *) *Atom, 0);
3153 gcmkFOOTER_ARG("*Atom=0x%X", *Atom);
3154 return gcvSTATUS_OK;
3157 /* Return the status. */
3162 /*******************************************************************************
3164 ** gckOS_AtomDestroy
3171 ** Pointer to a gckOS object.
3174 ** Pointer to the atom to destroy.
3188 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3190 /* Verify the arguments. */
3191 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3192 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3194 /* Free the atom. */
3195 gcmkONERROR(gcmkOS_SAFE_FREE(Os, Atom));
3199 return gcvSTATUS_OK;
3202 /* Return the status. */
3207 /*******************************************************************************
3211 ** Get the 32-bit value protected by an atom.
3216 ** Pointer to a gckOS object.
3219 ** Pointer to the atom.
3223 ** gctINT32_PTR Value
3224 ** Pointer to a variable the receives the value of the atom.
3230 OUT gctINT32_PTR Value
3233 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3235 /* Verify the arguments. */
3236 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3237 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3239 /* Return the current value of atom. */
3240 *Value = atomic_read((atomic_t *) Atom);
3243 gcmkFOOTER_ARG("*Value=%d", *Value);
3244 return gcvSTATUS_OK;
3247 /*******************************************************************************
3251 ** Set the 32-bit value protected by an atom.
3256 ** Pointer to a gckOS object.
3259 ** Pointer to the atom.
3262 ** The value of the atom.
3275 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x Value=%d", Os, Atom);
3277 /* Verify the arguments. */
3278 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3279 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3281 /* Set the current value of atom. */
3282 atomic_set((atomic_t *) Atom, Value);
3286 return gcvSTATUS_OK;
3289 /*******************************************************************************
3291 ** gckOS_AtomIncrement
3293 ** Atomically increment the 32-bit integer value inside an atom.
3298 ** Pointer to a gckOS object.
3301 ** Pointer to the atom.
3305 ** gctINT32_PTR Value
3306 ** Pointer to a variable that receives the original value of the atom.
3309 gckOS_AtomIncrement(
3312 OUT gctINT32_PTR Value
3315 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3317 /* Verify the arguments. */
3318 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3319 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3321 /* Increment the atom. */
3322 *Value = atomic_inc_return((atomic_t *) Atom) - 1;
3325 gcmkFOOTER_ARG("*Value=%d", *Value);
3326 return gcvSTATUS_OK;
3329 /*******************************************************************************
3331 ** gckOS_AtomDecrement
3333 ** Atomically decrement the 32-bit integer value inside an atom.
3338 ** Pointer to a gckOS object.
3341 ** Pointer to the atom.
3345 ** gctINT32_PTR Value
3346 ** Pointer to a variable that receives the original value of the atom.
3349 gckOS_AtomDecrement(
3352 OUT gctINT32_PTR Value
3355 gcmkHEADER_ARG("Os=0x%X Atom=0x%0x", Os, Atom);
3357 /* Verify the arguments. */
3358 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3359 gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
3361 /* Decrement the atom. */
3362 *Value = atomic_dec_return((atomic_t *) Atom) + 1;
3365 gcmkFOOTER_ARG("*Value=%d", *Value);
3366 return gcvSTATUS_OK;
3369 /*******************************************************************************
3373 ** Delay execution of the current thread for a number of milliseconds.
3378 ** Pointer to an gckOS object.
3381 ** Delay to sleep, specified in milliseconds.
3393 gcmkHEADER_ARG("Os=0x%X Delay=%u", Os, Delay);
3397 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)
3398 ktime_t delay = ktime_set((Delay / MSEC_PER_SEC), (Delay % MSEC_PER_SEC) * NSEC_PER_MSEC);
3399 __set_current_state(TASK_UNINTERRUPTIBLE);
3400 schedule_hrtimeout(&delay, HRTIMER_MODE_REL);
3408 return gcvSTATUS_OK;
3411 /*******************************************************************************
3415 ** Get the number of milliseconds since the system started.
3421 ** gctUINT32_PTR Time
3422 ** Pointer to a variable to get time.
3427 OUT gctUINT32_PTR Time
3432 *Time = jiffies_to_msecs(jiffies);
3435 return gcvSTATUS_OK;
3438 /*******************************************************************************
3442 ** Compare time values got from gckOS_GetTicks.
3446 ** First time value to be compared.
3449 ** Second time value to be compared.
3453 ** gctBOOL_PTR IsAfter
3454 ** Pointer to a variable to result.
3461 OUT gctBOOL_PTR IsAfter
3466 *IsAfter = time_after((unsigned long)Time1, (unsigned long)Time2);
3469 return gcvSTATUS_OK;
3472 /*******************************************************************************
3476 ** Get the number of microseconds since the system started.
3482 ** gctUINT64_PTR Time
3483 ** Pointer to a variable to get time.
3488 OUT gctUINT64_PTR Time
3494 /* Return the time of day in microseconds. */
3495 do_gettimeofday(&tv);
3496 *Time = (tv.tv_sec * 1000000ULL) + tv.tv_usec;
3499 return gcvSTATUS_OK;
3502 /*******************************************************************************
3504 ** gckOS_MemoryBarrier
3506 ** Make sure the CPU has executed everything up to this point and the data got
3507 ** written to the specified pointer.
3512 ** Pointer to an gckOS object.
3514 ** gctPOINTER Address
3515 ** Address of memory that needs to be barriered.
3522 gckOS_MemoryBarrier(
3524 IN gctPOINTER Address
3527 gcmkHEADER_ARG("Os=0x%X Address=0x%X", Os, Address);
3529 /* Verify the arguments. */
3530 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3532 #if gcdNONPAGED_MEMORY_BUFFERABLE \
3533 && defined (CONFIG_ARM) \
3534 && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34))
3535 /* drain write buffer */
3538 /* drain outer cache's write buffer? */
3545 return gcvSTATUS_OK;
3548 /*******************************************************************************
3550 ** gckOS_AllocatePagedMemory
3552 ** Allocate memory from the paged pool.
3557 ** Pointer to an gckOS object.
3560 ** Number of bytes to allocate.
3564 ** gctPHYS_ADDR * Physical
3565 ** Pointer to a variable that receives the physical address of the
3566 ** memory allocation.
3569 gckOS_AllocatePagedMemory(
3572 OUT gctPHYS_ADDR * Physical
3577 gcmkHEADER_ARG("Os=0x%X Bytes=%lu", Os, Bytes);
3579 /* Verify the arguments. */
3580 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3581 gcmkVERIFY_ARGUMENT(Bytes > 0);
3582 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3584 /* Allocate the memory. */
3585 gcmkONERROR(gckOS_AllocatePagedMemoryEx(Os, gcvALLOC_FLAG_NONE, Bytes, gcvNULL, Physical));
3588 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3589 return gcvSTATUS_OK;
3592 /* Return the status. */
3597 /*******************************************************************************
3599 ** gckOS_AllocatePagedMemoryEx
3601 ** Allocate memory from the paged pool.
3606 ** Pointer to an gckOS object.
3609 ** Allocation attribute.
3612 ** Number of bytes to allocate.
3617 ** Save the global ID for the piece of allocated memory.
3619 ** gctPHYS_ADDR * Physical
3620 ** Pointer to a variable that receives the physical address of the
3621 ** memory allocation.
3624 gckOS_AllocatePagedMemoryEx(
3628 OUT gctUINT32 * Gid,
3629 OUT gctPHYS_ADDR * Physical
3633 PLINUX_MDL mdl = gcvNULL;
3635 gceSTATUS status = gcvSTATUS_OUT_OF_MEMORY;
3636 gckALLOCATOR allocator;
3638 gcmkHEADER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
3640 /* Verify the arguments. */
3641 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3642 gcmkVERIFY_ARGUMENT(Bytes > 0);
3643 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3645 bytes = gcmALIGN(Bytes, PAGE_SIZE);
3647 numPages = GetPageCount(bytes, 0);
3652 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
3655 /* Walk all allocators. */
3656 list_for_each_entry(allocator, &Os->allocatorList, head)
3658 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
3659 "%s(%d) flag = %x allocator->capability = %x",
3660 __FUNCTION__, __LINE__, Flag, allocator->capability);
3662 if ((Flag & allocator->capability) != Flag)
3667 status = allocator->ops->Alloc(allocator, mdl, numPages, Flag);
3669 if (gcmIS_SUCCESS(status))
3671 mdl->allocator = allocator;
3677 gcmkONERROR(status);
3681 mdl->numPages = numPages;
3683 mdl->contiguous = Flag & gcvALLOC_FLAG_CONTIGUOUS;
3685 /* Return physical address. */
3686 *Physical = (gctPHYS_ADDR) mdl;
3696 * Add this to a global list.
3697 * Will be used by get physical address
3698 * and mapuser pointer functions.
3702 /* Initialize the queue. */
3703 Os->mdlHead = Os->mdlTail = mdl;
3708 mdl->prev = Os->mdlTail;
3709 Os->mdlTail->next = mdl;
3716 gcmkFOOTER_ARG("*Physical=0x%X", *Physical);
3717 return gcvSTATUS_OK;
3722 /* Free the memory. */
3725 *Physical = gcvNULL;
3727 /* Return the status. */
3728 gcmkFOOTER_ARG("Os=0x%X Flag=%x Bytes=%lu", Os, Flag, Bytes);
3732 /*******************************************************************************
3734 ** gckOS_FreePagedMemory
3736 ** Free memory allocated from the paged pool.
3741 ** Pointer to an gckOS object.
3743 ** gctPHYS_ADDR Physical
3744 ** Physical address of the allocation.
3747 ** Number of bytes of the allocation.
3754 gckOS_FreePagedMemory(
3756 IN gctPHYS_ADDR Physical,
3760 PLINUX_MDL mdl = (PLINUX_MDL) Physical;
3761 gckALLOCATOR allocator = (gckALLOCATOR)mdl->allocator;
3763 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Bytes);
3765 /* Verify the arguments. */
3766 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3767 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3768 gcmkVERIFY_ARGUMENT(Bytes > 0);
3772 /* Remove the node from global list. */
3773 if (mdl == Os->mdlHead)
3775 if ((Os->mdlHead = mdl->next) == gcvNULL)
3777 Os->mdlTail = gcvNULL;
3782 mdl->prev->next = mdl->next;
3784 if (mdl == Os->mdlTail)
3786 Os->mdlTail = mdl->prev;
3790 mdl->next->prev = mdl->prev;
3796 allocator->ops->Free(allocator, mdl);
3798 /* Free the structure... */
3799 gcmkVERIFY_OK(_DestroyMdl(mdl));
3803 return gcvSTATUS_OK;
3806 /*******************************************************************************
3810 ** Lock memory allocated from the paged pool.
3815 ** Pointer to an gckOS object.
3817 ** gctPHYS_ADDR Physical
3818 ** Physical address of the allocation.
3821 ** Number of bytes of the allocation.
3823 ** gctBOOL Cacheable
3824 ** Cache mode of mapping.
3828 ** gctPOINTER * Logical
3829 ** Pointer to a variable that receives the address of the mapped
3832 ** gctSIZE_T * PageCount
3833 ** Pointer to a variable that receives the number of pages required for
3834 ** the page table according to the GPU page size.
3839 IN gctPHYS_ADDR Physical,
3841 IN gctBOOL Cacheable,
3842 OUT gctPOINTER * Logical,
3843 OUT gctSIZE_T * PageCount
3848 PLINUX_MDL_MAP mdlMap;
3849 gckALLOCATOR allocator;
3851 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%lu", Os, Physical, Logical);
3853 /* Verify the arguments. */
3854 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3855 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3856 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
3857 gcmkVERIFY_ARGUMENT(PageCount != gcvNULL);
3859 mdl = (PLINUX_MDL) Physical;
3860 allocator = mdl->allocator;
3864 mdlMap = FindMdlMap(mdl, _GetProcessID());
3866 if (mdlMap == gcvNULL)
3868 mdlMap = _CreateMdlMap(mdl, _GetProcessID());
3870 if (mdlMap == gcvNULL)
3874 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
3875 return gcvSTATUS_OUT_OF_MEMORY;
3879 if (mdlMap->vmaAddr == gcvNULL)
3881 status = allocator->ops->MapUser(allocator, mdl, mdlMap, Cacheable);
3883 if (gcmIS_ERROR(status))
3887 gcmkFOOTER_ARG("*status=%d", status);
3894 /* Convert pointer to MDL. */
3895 *Logical = mdlMap->vmaAddr;
3897 /* Return the page number according to the GPU page size. */
3898 gcmkASSERT((PAGE_SIZE % 4096) == 0);
3899 gcmkASSERT((PAGE_SIZE / 4096) >= 1);
3901 *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
3905 gcmkVERIFY_OK(gckOS_CacheFlush(
3910 (gctPOINTER)mdlMap->vmaAddr,
3911 mdl->numPages * PAGE_SIZE
3915 gcmkFOOTER_ARG("*Logical=0x%X *PageCount=%lu", *Logical, *PageCount);
3916 return gcvSTATUS_OK;
3919 /*******************************************************************************
3923 ** Map paged memory into a page table.
3928 ** Pointer to an gckOS object.
3930 ** gctPHYS_ADDR Physical
3931 ** Physical address of the allocation.
3933 ** gctSIZE_T PageCount
3934 ** Number of pages required for the physical address.
3936 ** gctPOINTER PageTable
3937 ** Pointer to the page table to fill in.
3946 IN gctPHYS_ADDR Physical,
3947 IN gctSIZE_T PageCount,
3948 IN gctPOINTER PageTable
3951 return gckOS_MapPagesEx(Os,
3963 IN gctPHYS_ADDR Physical,
3964 IN gctSIZE_T PageCount,
3965 IN gctUINT32 Address,
3966 IN gctPOINTER PageTable
3969 gceSTATUS status = gcvSTATUS_OK;
3973 #if gcdNONPAGED_MEMORY_CACHEABLE
3977 gctPHYS_ADDR pageTablePhysical;
3980 #if gcdPROCESS_ADDRESS_SPACE
3981 gckKERNEL kernel = Os->device->kernels[Core];
3984 gckALLOCATOR allocator;
3986 gcmkHEADER_ARG("Os=0x%X Core=%d Physical=0x%X PageCount=%u PageTable=0x%X",
3987 Os, Core, Physical, PageCount, PageTable);
3989 /* Verify the arguments. */
3990 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3991 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
3992 gcmkVERIFY_ARGUMENT(PageCount > 0);
3993 gcmkVERIFY_ARGUMENT(PageTable != gcvNULL);
3995 /* Convert pointer to MDL. */
3996 mdl = (PLINUX_MDL)Physical;
3998 allocator = mdl->allocator;
4001 gcvLEVEL_INFO, gcvZONE_OS,
4002 "%s(%d): Physical->0x%X PageCount->0x%X PagedMemory->?%d",
4003 __FUNCTION__, __LINE__,
4004 (gctUINT32)(gctUINTPTR_T)Physical,
4005 (gctUINT32)(gctUINTPTR_T)PageCount,
4009 #if gcdPROCESS_ADDRESS_SPACE
4010 gcmkONERROR(gckKERNEL_GetProcessMMU(kernel, &mmu));
4013 table = (gctUINT32 *)PageTable;
4014 #if gcdNONPAGED_MEMORY_CACHEABLE
4015 mmu = Os->device->kernels[Core]->mmu;
4016 bytes = PageCount * sizeof(*table);
4017 mmuMdl = (PLINUX_MDL)mmu->pageTablePhysical;
4020 /* Get all the physical addresses and store them in the page table. */
4023 PageCount = PageCount / (PAGE_SIZE / 4096);
4025 /* Try to get the user pages so DMA can happen. */
4026 while (PageCount-- > 0)
4029 gctUINT32 phys = ~0;
4031 if (mdl->pagedMem && !mdl->contiguous)
4033 allocator->ops->Physical(allocator, mdl, offset, &phys);
4040 gcvLEVEL_INFO, gcvZONE_OS,
4041 "%s(%d): we should not get this call for Non Paged Memory!",
4042 __FUNCTION__, __LINE__
4046 phys = page_to_phys(nth_page(mdl->u.contiguousPages, offset));
4049 gcmkVERIFY_OK(gckOS_CPUPhysicalToGPUPhysical(Os, phys, &phys));
4051 #ifdef CONFIG_IOMMU_SUPPORT
4055 gcvLEVEL_INFO, gcvZONE_OS,
4056 "%s(%d): Setup mapping in IOMMU %x => %x",
4057 __FUNCTION__, __LINE__,
4058 Address + (offset * PAGE_SIZE), phys
4061 /* When use IOMMU, GPU use system PAGE_SIZE. */
4062 gcmkONERROR(gckIOMMU_Map(
4063 Os->iommu, Address + (offset * PAGE_SIZE), phys, PAGE_SIZE));
4070 if (Core == gcvCORE_VG)
4072 for (i = 0; i < (PAGE_SIZE / 4096); i++)
4075 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
4083 for (i = 0; i < (PAGE_SIZE / 4096); i++)
4085 #if gcdPROCESS_ADDRESS_SPACE
4086 gctUINT32_PTR pageTableEntry;
4087 gckMMU_GetPageEntry(mmu, Address + (offset * 4096), &pageTableEntry);
4094 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
4105 #if gcdNONPAGED_MEMORY_CACHEABLE
4106 /* Get physical address of pageTable */
4107 pageTablePhysical = (gctPHYS_ADDR)(mmuMdl->dmaHandle +
4108 ((gctUINT32 *)PageTable - mmu->pageTableLogical));
4110 /* Flush the mmu page table cache. */
4111 gcmkONERROR(gckOS_CacheClean(
4123 /* Return the status. */
4131 IN gctSIZE_T PageCount,
4132 IN gctUINT32 Address
4135 #ifdef CONFIG_IOMMU_SUPPORT
4138 gcmkVERIFY_OK(gckIOMMU_Unmap(
4139 Os->iommu, Address, PageCount * PAGE_SIZE));
4143 return gcvSTATUS_OK;
4146 /*******************************************************************************
4148 ** gckOS_UnlockPages
4150 ** Unlock memory allocated from the paged pool.
4155 ** Pointer to an gckOS object.
4157 ** gctPHYS_ADDR Physical
4158 ** Physical address of the allocation.
4161 ** Number of bytes of the allocation.
4163 ** gctPOINTER Logical
4164 ** Address of the mapped memory.
4173 IN gctPHYS_ADDR Physical,
4175 IN gctPOINTER Logical
4178 PLINUX_MDL_MAP mdlMap;
4179 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
4180 gckALLOCATOR allocator = mdl->allocator;
4182 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Bytes=%u Logical=0x%X",
4183 Os, Physical, Bytes, Logical);
4185 /* Verify the arguments. */
4186 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4187 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4188 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4194 while (mdlMap != gcvNULL)
4196 if ((mdlMap->vmaAddr != gcvNULL) && (_GetProcessID() == mdlMap->pid))
4198 if (--mdlMap->count == 0)
4200 allocator->ops->UnmapUser(
4203 mdl->numPages * PAGE_SIZE);
4205 mdlMap->vmaAddr = gcvNULL;
4209 mdlMap = mdlMap->next;
4216 return gcvSTATUS_OK;
4220 /*******************************************************************************
4222 ** gckOS_AllocateContiguous
4224 ** Allocate memory from the contiguous pool.
4229 ** Pointer to an gckOS object.
4231 ** gctBOOL InUserSpace
4232 ** gcvTRUE if the pages need to be mapped into user space.
4234 ** gctSIZE_T * Bytes
4235 ** Pointer to the number of bytes to allocate.
4239 ** gctSIZE_T * Bytes
4240 ** Pointer to a variable that receives the number of bytes allocated.
4242 ** gctPHYS_ADDR * Physical
4243 ** Pointer to a variable that receives the physical address of the
4244 ** memory allocation.
4246 ** gctPOINTER * Logical
4247 ** Pointer to a variable that receives the logical address of the
4248 ** memory allocation.
4251 gckOS_AllocateContiguous(
4253 IN gctBOOL InUserSpace,
4254 IN OUT gctSIZE_T * Bytes,
4255 OUT gctPHYS_ADDR * Physical,
4256 OUT gctPOINTER * Logical
4261 gcmkHEADER_ARG("Os=0x%X InUserSpace=%d *Bytes=%lu",
4262 Os, InUserSpace, gcmOPT_VALUE(Bytes));
4264 /* Verify the arguments. */
4265 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4266 gcmkVERIFY_ARGUMENT(Bytes != gcvNULL);
4267 gcmkVERIFY_ARGUMENT(*Bytes > 0);
4268 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4269 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4271 /* Same as non-paged memory for now. */
4272 gcmkONERROR(gckOS_AllocateNonPagedMemory(Os,
4279 gcmkFOOTER_ARG("*Bytes=%lu *Physical=0x%X *Logical=0x%X",
4280 *Bytes, *Physical, *Logical);
4281 return gcvSTATUS_OK;
4284 /* Return the status. */
4289 /*******************************************************************************
4291 ** gckOS_FreeContiguous
4293 ** Free memory allocated from the contiguous pool.
4298 ** Pointer to an gckOS object.
4300 ** gctPHYS_ADDR Physical
4301 ** Physical address of the allocation.
4303 ** gctPOINTER Logical
4304 ** Logicval address of the allocation.
4307 ** Number of bytes of the allocation.
4314 gckOS_FreeContiguous(
4316 IN gctPHYS_ADDR Physical,
4317 IN gctPOINTER Logical,
4323 gcmkHEADER_ARG("Os=0x%X Physical=0x%X Logical=0x%X Bytes=%lu",
4324 Os, Physical, Logical, Bytes);
4326 /* Verify the arguments. */
4327 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4328 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
4329 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
4330 gcmkVERIFY_ARGUMENT(Bytes > 0);
4332 /* Same of non-paged memory for now. */
4333 gcmkONERROR(gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical));
4337 return gcvSTATUS_OK;
4340 /* Return the status. */
4346 /******************************************************************************
4348 ** gckOS_GetKernelLogical
4350 ** Return the kernel logical pointer that corresponods to the specified
4351 ** hardware address.
4356 ** Pointer to an gckOS object.
4358 ** gctUINT32 Address
4359 ** Hardware physical address.
4363 ** gctPOINTER * KernelPointer
4364 ** Pointer to a variable receiving the pointer in kernel address space.
4367 gckOS_GetKernelLogical(
4369 IN gctUINT32 Address,
4370 OUT gctPOINTER * KernelPointer
4373 return gckOS_GetKernelLogicalEx(Os, gcvCORE_MAJOR, Address, KernelPointer);
4377 gckOS_GetKernelLogicalEx(
4380 IN gctUINT32 Address,
4381 OUT gctPOINTER * KernelPointer
4386 gcmkHEADER_ARG("Os=0x%X Core=%d Address=0x%08x", Os, Core, Address);
4390 gckGALDEVICE device;
4396 /* Extract the pointer to the gckGALDEVICE class. */
4397 device = (gckGALDEVICE) Os->device;
4399 /* Kernel shortcut. */
4400 kernel = device->kernels[Core];
4402 if (Core == gcvCORE_VG)
4404 gcmkERR_BREAK(gckVGHARDWARE_SplitMemory(
4405 kernel->vg->hardware, Address, &pool, &offset
4411 /* Split the memory address into a pool type and offset. */
4412 gcmkERR_BREAK(gckHARDWARE_SplitMemory(
4413 kernel->hardware, Address, &pool, &offset
4417 /* Dispatch on pool. */
4420 case gcvPOOL_LOCAL_INTERNAL:
4421 /* Internal memory. */
4422 logical = device->internalLogical;
4425 case gcvPOOL_LOCAL_EXTERNAL:
4426 /* External memory. */
4427 logical = device->externalLogical;
4430 case gcvPOOL_SYSTEM:
4431 /* System memory. */
4432 logical = device->contiguousBase;
4436 /* Invalid memory pool. */
4438 return gcvSTATUS_INVALID_ARGUMENT;
4441 /* Build logical address of specified address. */
4442 * KernelPointer = ((gctUINT8_PTR) logical) + offset;
4445 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4446 return gcvSTATUS_OK;
4450 /* Return status. */
4456 /*******************************************************************************
4458 ** gckOS_MapUserPointer
4460 ** Map a pointer from the user process into the kernel address space.
4465 ** Pointer to an gckOS object.
4467 ** gctPOINTER Pointer
4468 ** Pointer in user process space that needs to be mapped.
4471 ** Number of bytes that need to be mapped.
4475 ** gctPOINTER * KernelPointer
4476 ** Pointer to a variable receiving the mapped pointer in kernel address
4480 gckOS_MapUserPointer(
4482 IN gctPOINTER Pointer,
4484 OUT gctPOINTER * KernelPointer
4487 gctPOINTER buf = gcvNULL;
4490 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu", Os, Pointer, Size);
4492 /* Verify the arguments. */
4493 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4494 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4495 gcmkVERIFY_ARGUMENT(Size > 0);
4496 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4498 buf = kmalloc(Size, GFP_KERNEL | gcdNOWARN);
4503 "%s(%d): Failed to allocate memory.",
4504 __FUNCTION__, __LINE__
4507 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_OUT_OF_MEMORY);
4508 return gcvSTATUS_OUT_OF_MEMORY;
4511 len = copy_from_user(buf, Pointer, Size);
4516 "%s(%d): Failed to copy data from user.",
4517 __FUNCTION__, __LINE__
4525 gcmkFOOTER_ARG("*status=%d", gcvSTATUS_GENERIC_IO);
4526 return gcvSTATUS_GENERIC_IO;
4529 *KernelPointer = buf;
4531 gcmkFOOTER_ARG("*KernelPointer=0x%X", *KernelPointer);
4532 return gcvSTATUS_OK;
4535 /*******************************************************************************
4537 ** gckOS_UnmapUserPointer
4539 ** Unmap a user process pointer from the kernel address space.
4544 ** Pointer to an gckOS object.
4546 ** gctPOINTER Pointer
4547 ** Pointer in user process space that needs to be unmapped.
4550 ** Number of bytes that need to be unmapped.
4552 ** gctPOINTER KernelPointer
4553 ** Pointer in kernel address space that needs to be unmapped.
4560 gckOS_UnmapUserPointer(
4562 IN gctPOINTER Pointer,
4564 IN gctPOINTER KernelPointer
4569 gcmkHEADER_ARG("Os=0x%X Pointer=0x%X Size=%lu KernelPointer=0x%X",
4570 Os, Pointer, Size, KernelPointer);
4573 /* Verify the arguments. */
4574 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4575 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4576 gcmkVERIFY_ARGUMENT(Size > 0);
4577 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4579 len = copy_to_user(Pointer, KernelPointer, Size);
4581 kfree(KernelPointer);
4587 "%s(%d): Failed to copy data to user.",
4588 __FUNCTION__, __LINE__
4591 gcmkFOOTER_ARG("status=%d", gcvSTATUS_GENERIC_IO);
4592 return gcvSTATUS_GENERIC_IO;
4596 return gcvSTATUS_OK;
4599 /*******************************************************************************
4601 ** gckOS_QueryNeedCopy
4603 ** Query whether the memory can be accessed or mapped directly or it has to be
4609 ** Pointer to an gckOS object.
4611 ** gctUINT32 ProcessID
4612 ** Process ID of the current process.
4616 ** gctBOOL_PTR NeedCopy
4617 ** Pointer to a boolean receiving gcvTRUE if the memory needs a copy or
4618 ** gcvFALSE if the memory can be accessed or mapped dircetly.
4621 gckOS_QueryNeedCopy(
4623 IN gctUINT32 ProcessID,
4624 OUT gctBOOL_PTR NeedCopy
4627 gcmkHEADER_ARG("Os=0x%X ProcessID=%d", Os, ProcessID);
4629 /* Verify the arguments. */
4630 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4631 gcmkVERIFY_ARGUMENT(NeedCopy != gcvNULL);
4633 /* We need to copy data. */
4634 *NeedCopy = gcvTRUE;
4637 gcmkFOOTER_ARG("*NeedCopy=%d", *NeedCopy);
4638 return gcvSTATUS_OK;
4641 /*******************************************************************************
4643 ** gckOS_CopyFromUserData
4645 ** Copy data from user to kernel memory.
4650 ** Pointer to an gckOS object.
4652 ** gctPOINTER KernelPointer
4653 ** Pointer to kernel memory.
4655 ** gctPOINTER Pointer
4656 ** Pointer to user memory.
4659 ** Number of bytes to copy.
4666 gckOS_CopyFromUserData(
4668 IN gctPOINTER KernelPointer,
4669 IN gctPOINTER Pointer,
4675 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
4676 Os, KernelPointer, Pointer, Size);
4678 /* Verify the arguments. */
4679 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4680 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4681 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4682 gcmkVERIFY_ARGUMENT(Size > 0);
4684 /* Copy data from user. */
4685 if (copy_from_user(KernelPointer, Pointer, Size) != 0)
4687 /* Could not copy all the bytes. */
4688 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4693 return gcvSTATUS_OK;
4696 /* Return the status. */
4701 /*******************************************************************************
4703 ** gckOS_CopyToUserData
4705 ** Copy data from kernel to user memory.
4710 ** Pointer to an gckOS object.
4712 ** gctPOINTER KernelPointer
4713 ** Pointer to kernel memory.
4715 ** gctPOINTER Pointer
4716 ** Pointer to user memory.
4719 ** Number of bytes to copy.
4726 gckOS_CopyToUserData(
4728 IN gctPOINTER KernelPointer,
4729 IN gctPOINTER Pointer,
4735 gcmkHEADER_ARG("Os=0x%X KernelPointer=0x%X Pointer=0x%X Size=%lu",
4736 Os, KernelPointer, Pointer, Size);
4738 /* Verify the arguments. */
4739 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4740 gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
4741 gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
4742 gcmkVERIFY_ARGUMENT(Size > 0);
4744 /* Copy data to user. */
4745 if (copy_to_user(Pointer, KernelPointer, Size) != 0)
4747 /* Could not copy all the bytes. */
4748 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
4753 return gcvSTATUS_OK;
4756 /* Return the status. */
4761 /*******************************************************************************
4763 ** gckOS_WriteMemory
4765 ** Write data to a memory.
4770 ** Pointer to an gckOS object.
4772 ** gctPOINTER Address
4773 ** Address of the memory to write to.
4776 ** Data for register.
4785 IN gctPOINTER Address,
4790 gcmkHEADER_ARG("Os=0x%X Address=0x%X Data=%u", Os, Address, Data);
4792 /* Verify the arguments. */
4793 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4796 if (access_ok(VERIFY_WRITE, Address, 4))
4799 if(put_user(Data, (gctUINT32*)Address))
4801 gcmkONERROR(gcvSTATUS_INVALID_ADDRESS);
4806 /* Kernel address. */
4807 *(gctUINT32 *)Address = Data;
4812 return gcvSTATUS_OK;
4819 /*******************************************************************************
4821 ** gckOS_MapUserMemory
4823 ** Lock down a user buffer and return an DMA'able address to be used by the
4824 ** hardware to access it.
4828 ** gctPOINTER Memory
4829 ** Pointer to memory to lock down.
4832 ** Size in bytes of the memory to lock down.
4836 ** gctPOINTER * Info
4837 ** Pointer to variable receiving the information record required by
4838 ** gckOS_UnmapUserMemory.
4840 ** gctUINT32_PTR Address
4841 ** Pointer to a variable that will receive the address DMA'able by the
4845 gckOS_MapUserMemory(
4848 IN gctPOINTER Memory,
4849 IN gctUINT32 Physical,
4851 OUT gctPOINTER * Info,
4852 OUT gctUINT32_PTR Address
4857 gcmkHEADER_ARG("Os=0x%x Core=%d Memory=0x%x Size=%lu", Os, Core, Memory, Size);
4860 gcmkONERROR(gckOS_AddMapping(Os, *Address, Memory, Size));
4863 return gcvSTATUS_OK;
4870 gctSIZE_T pageCount, i, j;
4871 gctUINT32_PTR pageTable;
4872 gctUINT32 address = 0, physical = ~0U;
4873 gctUINTPTR_T start, end, memory;
4876 #if gcdPROCESS_ADDRESS_SPACE
4880 gcsPageInfo_PTR info = gcvNULL;
4881 struct page **pages = gcvNULL;
4883 /* Verify the arguments. */
4884 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4885 gcmkVERIFY_ARGUMENT(Memory != gcvNULL || Physical != ~0U);
4886 gcmkVERIFY_ARGUMENT(Size > 0);
4887 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
4888 gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4892 gctSIZE_T extraPage;
4894 memory = (gctUINTPTR_T) Memory;
4896 /* Get the number of required pages. */
4897 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
4898 start = memory >> PAGE_SHIFT;
4899 pageCount = end - start;
4901 /* Allocate extra 64 bytes to avoid cache overflow */
4902 extraPage = (((memory + gcmALIGN(Size + 64, 64) + PAGE_SIZE - 1) >> PAGE_SHIFT) > end) ? 1 : 0;
4905 gcvLEVEL_INFO, gcvZONE_OS,
4906 "%s(%d): pageCount: %d.",
4907 __FUNCTION__, __LINE__,
4912 if ((memory + Size) < memory)
4914 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
4915 return gcvSTATUS_INVALID_ARGUMENT;
4918 MEMORY_MAP_LOCK(Os);
4920 /* Allocate the Info struct. */
4921 info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL | gcdNOWARN);
4923 if (info == gcvNULL)
4925 status = gcvSTATUS_OUT_OF_MEMORY;
4929 info->extraPage = 0;
4931 /* Allocate the array of page addresses. */
4932 pages = (struct page **)kmalloc((pageCount + extraPage) * sizeof(struct page *), GFP_KERNEL | gcdNOWARN);
4934 if (pages == gcvNULL)
4936 status = gcvSTATUS_OUT_OF_MEMORY;
4940 if (Physical != ~0U)
4942 for (i = 0; i < pageCount; i++)
4944 pages[i] = pfn_to_page((Physical >> PAGE_SHIFT) + i);
4946 if (pfn_valid(page_to_pfn(pages[i])))
4954 /* Get the user pages. */
4955 down_read(¤t->mm->mmap_sem);
4957 result = get_user_pages(current,
4967 up_read(¤t->mm->mmap_sem);
4969 if (result <=0 || result < pageCount)
4971 struct vm_area_struct *vma;
4973 /* Release the pages if any. */
4976 for (i = 0; i < result; i++)
4978 if (pages[i] == gcvNULL)
4983 page_cache_release(pages[i]);
4990 vma = find_vma(current->mm, memory);
4992 if (vma && (vma->vm_flags & VM_PFNMAP))
4996 gctUINTPTR_T logical = memory;
4998 for (i = 0; i < pageCount; i++)
5000 pgd_t * pgd = pgd_offset(current->mm, logical);
5001 pud_t * pud = pud_offset(pgd, logical);
5005 pmd_t * pmd = pmd_offset(pud, logical);
5006 pte = pte_offset_map_lock(current->mm, pmd, logical, &ptl);
5009 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5014 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5017 pages[i] = pte_page(*pte);
5018 pte_unmap_unlock(pte, ptl);
5020 /* Advance to next. */
5021 logical += PAGE_SIZE;
5026 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
5029 /* Check if this memory is contiguous for old mmu. */
5030 if (Os->device->kernels[Core]->hardware->mmuVersion == 0)
5032 for (i = 1; i < pageCount; i++)
5034 if (pages[i] != nth_page(pages[0], i))
5036 /* Non-contiguous. */
5043 /* Contiguous memory. */
5044 physical = page_to_phys(pages[0]) | (memory & ~PAGE_MASK);
5046 if (!((physical - Os->device->baseAddress) & 0x80000000))
5051 info->pages = gcvNULL;
5052 info->pageTable = gcvNULL;
5054 MEMORY_MAP_UNLOCK(Os);
5056 *Address = physical - Os->device->baseAddress;
5060 gckOS_CPUPhysicalToGPUPhysical(Os, *Address, Address));
5062 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x",
5065 return gcvSTATUS_OK;
5070 /* Reference pages. */
5071 for (i = 0; i < pageCount; i++)
5073 if (pfn_valid(page_to_pfn(pages[i])))
5081 for (i = 0; i < pageCount; i++)
5085 get_user(data, (gctUINT32*)((memory & PAGE_MASK) + i * PAGE_SIZE));
5088 /* Flush(clean) the data cache. */
5089 gcmkONERROR(gckOS_CacheFlush(Os, _GetProcessID(), gcvNULL,
5090 page_to_phys(pages[i]),
5091 (gctPOINTER)(memory & PAGE_MASK) + i*PAGE_SIZE,
5095 #if gcdPROCESS_ADDRESS_SPACE
5096 gcmkONERROR(gckKERNEL_GetProcessMMU(Os->device->kernels[Core], &mmu));
5101 pages[pageCount++] = Os->paddingPage;
5102 info->extraPage = 1;
5107 gctPHYS_ADDR physicalArrayPhysical;
5108 gctPOINTER physicalArrayLogical;
5109 gctUINT32_PTR logical;
5110 gctSIZE_T bytes = pageCount * gcmSIZEOF(gctUINT32);
5111 pageTable = gcvNULL;
5113 gcmkONERROR(gckOS_AllocateNonPagedMemory(
5117 &physicalArrayPhysical,
5118 &physicalArrayLogical
5121 logical = physicalArrayLogical;
5123 /* Fill the page table. */
5124 for (i = 0; i < pageCount; i++)
5127 phys = page_to_phys(pages[i]);
5134 gcmkONERROR(gckKERNEL_SecurityMapMemory(
5135 Os->device->kernels[Core],
5136 physicalArrayLogical,
5141 gcmkONERROR(gckOS_FreeNonPagedMemory(
5144 physicalArrayPhysical,
5145 physicalArrayLogical
5151 if (Core == gcvCORE_VG)
5153 /* Allocate pages inside the page table. */
5154 gcmkERR_BREAK(gckVGMMU_AllocatePages(Os->device->kernels[Core]->vg->mmu,
5155 pageCount * (PAGE_SIZE/4096),
5156 (gctPOINTER *) &pageTable,
5162 #if gcdPROCESS_ADDRESS_SPACE
5163 /* Allocate pages inside the page table. */
5164 gcmkERR_BREAK(gckMMU_AllocatePages(mmu,
5165 pageCount * (PAGE_SIZE/4096),
5166 (gctPOINTER *) &pageTable,
5169 /* Allocate pages inside the page table. */
5170 gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernels[Core]->mmu,
5171 pageCount * (PAGE_SIZE/4096),
5172 (gctPOINTER *) &pageTable,
5177 /* Fill the page table. */
5178 for (i = 0; i < pageCount; i++)
5181 gctUINT32_PTR tab = pageTable + i * (PAGE_SIZE/4096);
5183 #if gcdPROCESS_ADDRESS_SPACE
5184 gckMMU_GetPageEntry(mmu, address + i * 4096, &tab);
5186 phys = page_to_phys(pages[i]);
5188 #ifdef CONFIG_IOMMU_SUPPORT
5192 gcvLEVEL_INFO, gcvZONE_OS,
5193 "%s(%d): Setup mapping in IOMMU %x => %x",
5194 __FUNCTION__, __LINE__,
5195 Address + (i * PAGE_SIZE), phys
5198 gcmkONERROR(gckIOMMU_Map(
5199 Os->iommu, address + i * PAGE_SIZE, phys, PAGE_SIZE));
5206 if (Core == gcvCORE_VG)
5209 gckOS_CPUPhysicalToGPUPhysical(Os, phys, &phys));
5211 /* Get the physical address from page struct. */
5213 gckVGMMU_SetPage(Os->device->kernels[Core]->vg->mmu,
5220 /* Get the physical address from page struct. */
5222 gckMMU_SetPage(Os->device->kernels[Core]->mmu,
5227 for (j = 1; j < (PAGE_SIZE/4096); j++)
5229 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
5233 #if !gcdPROCESS_ADDRESS_SPACE
5235 gcvLEVEL_INFO, gcvZONE_OS,
5236 "%s(%d): pageTable[%d]: 0x%X 0x%X.",
5237 __FUNCTION__, __LINE__,
5238 i, phys, pageTable[i]);
5243 if (Core == gcvCORE_VG)
5245 gcmkONERROR(gckVGMMU_Flush(Os->device->kernels[Core]->vg->mmu));
5250 #if gcdPROCESS_ADDRESS_SPACE
5252 gcmkONERROR(gckMMU_Flush(mmu));
5254 gcmkONERROR(gckMMU_Flush(Os->device->kernels[Core]->mmu, gcvSURF_TYPE_UNKNOWN));
5258 info->address = address;
5260 /* Save pointer to page table. */
5261 info->pageTable = pageTable;
5262 info->pages = pages;
5264 *Info = (gctPOINTER) info;
5267 gcvLEVEL_INFO, gcvZONE_OS,
5268 "%s(%d): info->pages: 0x%X, info->pageTable: 0x%X, info: 0x%X.",
5269 __FUNCTION__, __LINE__,
5275 offset = (Physical != ~0U)
5276 ? (Physical & ~PAGE_MASK)
5277 : (memory & ~PAGE_MASK);
5279 /* Return address. */
5280 *Address = address + offset;
5283 gcvLEVEL_INFO, gcvZONE_OS,
5284 "%s(%d): Address: 0x%X.",
5285 __FUNCTION__, __LINE__,
5290 status = gcvSTATUS_OK;
5296 if (gcmIS_ERROR(status))
5300 "%s(%d): error occured: %d.",
5301 __FUNCTION__, __LINE__,
5305 /* Release page array. */
5306 if (result > 0 && pages != gcvNULL)
5310 "%s(%d): error: page table is freed.",
5311 __FUNCTION__, __LINE__
5314 for (i = 0; i < result; i++)
5316 if (pages[i] == gcvNULL)
5320 page_cache_release(pages[i]);
5324 if (info!= gcvNULL && pages != gcvNULL)
5328 "%s(%d): error: pages is freed.",
5329 __FUNCTION__, __LINE__
5332 /* Free the page table. */
5334 info->pages = gcvNULL;
5337 /* Release page info struct. */
5338 if (info != gcvNULL)
5342 "%s(%d): error: info is freed.",
5343 __FUNCTION__, __LINE__
5346 /* Free the page info struct. */
5352 MEMORY_MAP_UNLOCK(Os);
5354 /* Return the status. */
5355 if (gcmIS_SUCCESS(status))
5357 gcmkFOOTER_ARG("*Info=0x%X *Address=0x%08x", *Info, *Address);
5369 /*******************************************************************************
5371 ** gckOS_UnmapUserMemory
5373 ** Unlock a user buffer and that was previously locked down by
5374 ** gckOS_MapUserMemory.
5378 ** gctPOINTER Memory
5379 ** Pointer to memory to unlock.
5382 ** Size in bytes of the memory to unlock.
5385 ** Information record returned by gckOS_MapUserMemory.
5387 ** gctUINT32_PTR Address
5388 ** The address returned by gckOS_MapUserMemory.
5395 gckOS_UnmapUserMemory(
5398 IN gctPOINTER Memory,
5401 IN gctUINT32 Address
5406 gcmkHEADER_ARG("Os=0x%X Core=%d Memory=0x%X Size=%lu Info=0x%X Address0x%08x",
5407 Os, Core, Memory, Size, Info, Address);
5410 gcmkONERROR(gckOS_RemoveMapping(Os, Memory, Size));
5413 return gcvSTATUS_OK;
5420 gctUINTPTR_T memory, start, end;
5421 gcsPageInfo_PTR info;
5422 gctSIZE_T pageCount, i;
5423 struct page **pages;
5425 /* Verify the arguments. */
5426 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5427 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5428 gcmkVERIFY_ARGUMENT(Size > 0);
5429 gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5433 info = (gcsPageInfo_PTR) Info;
5435 pages = info->pages;
5438 gcvLEVEL_INFO, gcvZONE_OS,
5439 "%s(%d): info=0x%X, pages=0x%X.",
5440 __FUNCTION__, __LINE__,
5444 /* Invalid page array. */
5445 if (pages == gcvNULL && info->pageTable == gcvNULL)
5450 return gcvSTATUS_OK;
5453 memory = (gctUINTPTR_T)Memory;
5454 end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5455 start = memory >> PAGE_SHIFT;
5456 pageCount = end - start;
5459 if ((memory + Size) < memory)
5461 gcmkFOOTER_ARG("status=%d", gcvSTATUS_INVALID_ARGUMENT);
5462 return gcvSTATUS_INVALID_ARGUMENT;
5466 gcvLEVEL_INFO, gcvZONE_OS,
5467 "%s(%d): memory: 0x%X, pageCount: %d, pageTable: 0x%X.",
5468 __FUNCTION__, __LINE__,
5469 memory, pageCount, info->pageTable
5472 MEMORY_MAP_LOCK(Os);
5475 gcmkASSERT(info->pageTable != gcvNULL);
5478 if (info->extraPage)
5484 if (info->address > 0x80000000)
5486 gckKERNEL_SecurityUnmapMemory(
5487 Os->device->kernels[Core],
5494 gcmkPRINT("Wrong address %s(%d) %x", __FUNCTION__, __LINE__, info->address);
5498 if (Core == gcvCORE_VG)
5500 /* Free the pages from the MMU. */
5501 gcmkERR_BREAK(gckVGMMU_FreePages(Os->device->kernels[Core]->vg->mmu,
5503 pageCount * (PAGE_SIZE/4096)
5509 /* Free the pages from the MMU. */
5510 #if gcdPROCESS_ADDRESS_SPACE
5511 gcmkERR_BREAK(gckMMU_FreePagesEx(info->mmu,
5513 pageCount * (PAGE_SIZE/4096)
5517 gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernels[Core]->mmu,
5519 pageCount * (PAGE_SIZE/4096)
5523 gcmkERR_BREAK(gckOS_UnmapPages(
5525 pageCount * (PAGE_SIZE/4096),
5531 if (info->extraPage)
5534 info->extraPage = 0;
5537 /* Release the page cache. */
5540 for (i = 0; i < pageCount; i++)
5543 gcvLEVEL_INFO, gcvZONE_OS,
5544 "%s(%d): pages[%d]: 0x%X.",
5545 __FUNCTION__, __LINE__,
5549 if (!PageReserved(pages[i]))
5551 SetPageDirty(pages[i]);
5554 if (pfn_valid(page_to_pfn(pages[i])))
5556 page_cache_release(pages[i]);
5562 status = gcvSTATUS_OK;
5566 if (info != gcvNULL)
5568 /* Free the page array. */
5569 if (info->pages != gcvNULL)
5577 MEMORY_MAP_UNLOCK(Os);
5579 /* Return the status. */
5586 /*******************************************************************************
5588 ** gckOS_GetBaseAddress
5590 ** Get the base address for the physical memory.
5595 ** Pointer to the gckOS object.
5599 ** gctUINT32_PTR BaseAddress
5600 ** Pointer to a variable that will receive the base address.
5603 gckOS_GetBaseAddress(
5605 OUT gctUINT32_PTR BaseAddress
5608 gcmkHEADER_ARG("Os=0x%X", Os);
5610 /* Verify the arguments. */
5611 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5612 gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5614 /* Return base address. */
5615 *BaseAddress = Os->device->baseAddress;
5618 gcmkFOOTER_ARG("*BaseAddress=0x%08x", *BaseAddress);
5619 return gcvSTATUS_OK;
5623 gckOS_SuspendInterrupt(
5627 return gckOS_SuspendInterruptEx(Os, gcvCORE_MAJOR);
5632 gckOS_SuspendInterruptEx(
5637 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5639 /* Verify the arguments. */
5640 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5642 if (Core == gcvCORE_MAJOR)
5644 disable_irq(Os->device->irqLine3D[gcvCORE_3D_0_ID]);
5645 disable_irq(Os->device->irqLine3D[gcvCORE_3D_1_ID]);
5649 disable_irq(Os->device->irqLines[Core]);
5653 return gcvSTATUS_OK;
5657 gckOS_SuspendInterruptEx(
5662 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5664 /* Verify the arguments. */
5665 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5667 disable_irq(Os->device->irqLines[Core]);
5670 return gcvSTATUS_OK;
5675 gckOS_ResumeInterrupt(
5679 return gckOS_ResumeInterruptEx(Os, gcvCORE_MAJOR);
5684 gckOS_ResumeInterruptEx(
5689 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5691 /* Verify the arguments. */
5692 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5694 if (Core == gcvCORE_MAJOR)
5696 enable_irq(Os->device->irqLine3D[gcvCORE_3D_0_ID]);
5697 enable_irq(Os->device->irqLine3D[gcvCORE_3D_1_ID]);
5701 enable_irq(Os->device->irqLines[Core]);
5705 return gcvSTATUS_OK;
5709 gckOS_ResumeInterruptEx(
5714 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
5716 /* Verify the arguments. */
5717 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5719 enable_irq(Os->device->irqLines[Core]);
5722 return gcvSTATUS_OK;
5728 IN gctPOINTER Destination,
5729 IN gctCONST_POINTER Source,
5733 gcmkHEADER_ARG("Destination=0x%X Source=0x%X Bytes=%lu",
5734 Destination, Source, Bytes);
5736 gcmkVERIFY_ARGUMENT(Destination != gcvNULL);
5737 gcmkVERIFY_ARGUMENT(Source != gcvNULL);
5738 gcmkVERIFY_ARGUMENT(Bytes > 0);
5740 memcpy(Destination, Source, Bytes);
5743 return gcvSTATUS_OK;
5748 IN gctPOINTER Memory,
5752 gcmkHEADER_ARG("Memory=0x%X Bytes=%lu", Memory, Bytes);
5754 gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5755 gcmkVERIFY_ARGUMENT(Bytes > 0);
5757 memset(Memory, 0, Bytes);
5760 return gcvSTATUS_OK;
5763 /*******************************************************************************
5764 ********************************* Cache Control ********************************
5765 *******************************************************************************/
5767 /*******************************************************************************
5770 ** Clean the cache for the specified addresses. The GPU is going to need the
5771 ** data. If the system is allocating memory as non-cachable, this function can
5777 ** Pointer to gckOS object.
5779 ** gctUINT32 ProcessID
5780 ** Process ID Logical belongs.
5782 ** gctPHYS_ADDR Handle
5783 ** Physical address handle. If gcvNULL it is video memory.
5785 ** gctPOINTER Physical
5786 ** Physical address to flush.
5788 ** gctPOINTER Logical
5789 ** Logical address to flush.
5792 ** Size of the address range in bytes to flush.
5797 IN gctUINT32 ProcessID,
5798 IN gctPHYS_ADDR Handle,
5799 IN gctUINT32 Physical,
5800 IN gctPOINTER Logical,
5804 gcsPLATFORM * platform;
5806 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5807 Os, ProcessID, Handle, Logical, Bytes);
5809 /* Verify the arguments. */
5810 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5811 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
5812 gcmkVERIFY_ARGUMENT(Bytes > 0);
5814 platform = Os->device->platform;
5816 if (platform && platform->ops->cache)
5818 platform->ops->cache(
5830 return gcvSTATUS_OK;
5833 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5837 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
5838 dmac_map_area(Logical, Bytes, DMA_TO_DEVICE);
5840 dmac_clean_range(Logical, Logical + Bytes);
5843 #if defined(CONFIG_OUTER_CACHE)
5845 #if gcdENABLE_OUTER_CACHE_PATCH
5846 _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_CLEAN);
5848 outer_clean_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
5852 #elif defined(CONFIG_MIPS)
5854 dma_cache_wback((unsigned long) Logical, Bytes);
5856 #elif defined(CONFIG_PPC)
5861 dma_sync_single_for_device(
5863 (dma_addr_t)Physical,
5871 return gcvSTATUS_OK;
5874 /*******************************************************************************
5875 ** gckOS_CacheInvalidate
5877 ** Invalidate the cache for the specified addresses. The GPU is going to need
5878 ** data. If the system is allocating memory as non-cachable, this function can
5884 ** Pointer to gckOS object.
5886 ** gctUINT32 ProcessID
5887 ** Process ID Logical belongs.
5889 ** gctPHYS_ADDR Handle
5890 ** Physical address handle. If gcvNULL it is video memory.
5892 ** gctPOINTER Logical
5893 ** Logical address to flush.
5896 ** Size of the address range in bytes to flush.
5899 gckOS_CacheInvalidate(
5901 IN gctUINT32 ProcessID,
5902 IN gctPHYS_ADDR Handle,
5903 IN gctUINT32 Physical,
5904 IN gctPOINTER Logical,
5908 gcsPLATFORM * platform;
5910 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
5911 Os, ProcessID, Handle, Logical, Bytes);
5913 /* Verify the arguments. */
5914 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5915 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
5916 gcmkVERIFY_ARGUMENT(Bytes > 0);
5918 platform = Os->device->platform;
5920 if (platform && platform->ops->cache)
5922 platform->ops->cache(
5934 return gcvSTATUS_OK;
5937 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
5941 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,35)
5942 dmac_map_area(Logical, Bytes, DMA_FROM_DEVICE);
5944 dmac_inv_range(Logical, Logical + Bytes);
5947 #if defined(CONFIG_OUTER_CACHE)
5949 #if gcdENABLE_OUTER_CACHE_PATCH
5950 _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_INVALIDATE);
5952 outer_inv_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
5956 #elif defined(CONFIG_MIPS)
5957 dma_cache_inv((unsigned long) Logical, Bytes);
5958 #elif defined(CONFIG_PPC)
5961 dma_sync_single_for_device(
5963 (dma_addr_t)Physical,
5971 return gcvSTATUS_OK;
5974 /*******************************************************************************
5977 ** Clean the cache for the specified addresses and invalidate the lines as
5978 ** well. The GPU is going to need and modify the data. If the system is
5979 ** allocating memory as non-cachable, this function can be ignored.
5984 ** Pointer to gckOS object.
5986 ** gctUINT32 ProcessID
5987 ** Process ID Logical belongs.
5989 ** gctPHYS_ADDR Handle
5990 ** Physical address handle. If gcvNULL it is video memory.
5992 ** gctPOINTER Logical
5993 ** Logical address to flush.
5996 ** Size of the address range in bytes to flush.
6001 IN gctUINT32 ProcessID,
6002 IN gctPHYS_ADDR Handle,
6003 IN gctUINT32 Physical,
6004 IN gctPOINTER Logical,
6008 gcsPLATFORM * platform;
6010 gcmkHEADER_ARG("Os=0x%X ProcessID=%d Handle=0x%X Logical=0x%X Bytes=%lu",
6011 Os, ProcessID, Handle, Logical, Bytes);
6013 /* Verify the arguments. */
6014 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6015 gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
6016 gcmkVERIFY_ARGUMENT(Bytes > 0);
6018 platform = Os->device->platform;
6020 if (platform && platform->ops->cache)
6022 platform->ops->cache(
6034 return gcvSTATUS_OK;
6037 #if !gcdCACHE_FUNCTION_UNIMPLEMENTED
6040 dmac_flush_range(Logical, Logical + Bytes);
6042 #if defined(CONFIG_OUTER_CACHE)
6044 #if gcdENABLE_OUTER_CACHE_PATCH
6045 _HandleOuterCache(Os, Physical, Logical, Bytes, gcvCACHE_FLUSH);
6047 outer_flush_range((unsigned long) Handle, (unsigned long) Handle + Bytes);
6051 #elif defined(CONFIG_MIPS)
6052 dma_cache_wback_inv((unsigned long) Logical, Bytes);
6053 #elif defined(CONFIG_PPC)
6056 dma_sync_single_for_device(
6058 (dma_addr_t)Physical,
6066 return gcvSTATUS_OK;
6069 /*******************************************************************************
6070 ********************************* Broadcasting *********************************
6071 *******************************************************************************/
6073 /*******************************************************************************
6077 ** System hook for broadcast events from the kernel driver.
6082 ** Pointer to the gckOS object.
6084 ** gckHARDWARE Hardware
6085 ** Pointer to the gckHARDWARE object.
6087 ** gceBROADCAST Reason
6088 ** Reason for the broadcast. Can be one of the following values:
6090 ** gcvBROADCAST_GPU_IDLE
6091 ** Broadcasted when the kernel driver thinks the GPU might be
6092 ** idle. This can be used to handle power management.
6094 ** gcvBROADCAST_GPU_COMMIT
6095 ** Broadcasted when any client process commits a command
6096 ** buffer. This can be used to handle power management.
6098 ** gcvBROADCAST_GPU_STUCK
6099 ** Broadcasted when the kernel driver hits the timeout waiting
6102 ** gcvBROADCAST_FIRST_PROCESS
6103 ** First process is trying to connect to the kernel.
6105 ** gcvBROADCAST_LAST_PROCESS
6106 ** Last process has detached from the kernel.
6115 IN gckHARDWARE Hardware,
6116 IN gceBROADCAST Reason
6121 gcmkHEADER_ARG("Os=0x%X Hardware=0x%X Reason=%d", Os, Hardware, Reason);
6123 /* Verify the arguments. */
6124 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6125 gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
6129 case gcvBROADCAST_FIRST_PROCESS:
6130 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
6133 case gcvBROADCAST_LAST_PROCESS:
6134 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
6138 gckHARDWARE_SetPowerManagementState(Hardware,
6139 gcvPOWER_OFF_BROADCAST));
6142 case gcvBROADCAST_GPU_IDLE:
6143 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
6147 gckHARDWARE_SetPowerManagementState(Hardware,
6148 #if gcdPOWER_SUSPEND_WHEN_IDLE
6149 gcvPOWER_SUSPEND_BROADCAST));
6151 gcvPOWER_IDLE_BROADCAST));
6154 /* Add idle process DB. */
6155 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6158 gcvNULL, gcvNULL, 0));
6161 case gcvBROADCAST_GPU_COMMIT:
6162 gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
6164 /* Add busy process DB. */
6165 gcmkONERROR(gckKERNEL_AddProcessDB(Hardware->kernel,
6168 gcvNULL, gcvNULL, 0));
6172 gckHARDWARE_SetPowerManagementState(Hardware, gcvPOWER_ON_AUTO));
6175 case gcvBROADCAST_GPU_STUCK:
6176 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_GPU_STUCK\n");
6177 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6180 case gcvBROADCAST_AXI_BUS_ERROR:
6181 gcmkTRACE_N(gcvLEVEL_ERROR, 0, "gcvBROADCAST_AXI_BUS_ERROR\n");
6182 gcmkONERROR(gckHARDWARE_DumpGPUState(Hardware));
6183 gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
6186 case gcvBROADCAST_OUT_OF_MEMORY:
6187 gcmkTRACE_N(gcvLEVEL_INFO, 0, "gcvBROADCAST_OUT_OF_MEMORY\n");
6189 status = _ShrinkMemory(Os);
6191 if (status == gcvSTATUS_NOT_SUPPORTED)
6196 gcmkONERROR(status);
6201 /* Skip unimplemented broadcast. */
6207 return gcvSTATUS_OK;
6210 /* Return the status. */
6215 /*******************************************************************************
6217 ** gckOS_BroadcastHurry
6219 ** The GPU is running too slow.
6224 ** Pointer to the gckOS object.
6226 ** gckHARDWARE Hardware
6227 ** Pointer to the gckHARDWARE object.
6230 ** The higher the number, the higher the urgency to speed up the GPU.
6231 ** The maximum value is defined by the gcdDYNAMIC_EVENT_THRESHOLD.
6238 gckOS_BroadcastHurry(
6240 IN gckHARDWARE Hardware,
6244 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Urgency=%u", Os, Hardware, Urgency);
6246 /* Do whatever you need to do to speed up the GPU now. */
6250 return gcvSTATUS_OK;
6253 /*******************************************************************************
6255 ** gckOS_BroadcastCalibrateSpeed
6257 ** Calibrate the speed of the GPU.
6262 ** Pointer to the gckOS object.
6264 ** gckHARDWARE Hardware
6265 ** Pointer to the gckHARDWARE object.
6267 ** gctUINT Idle, Time
6268 ** Idle/Time will give the percentage the GPU is idle, so you can use
6269 ** this to calibrate the working point of the GPU.
6276 gckOS_BroadcastCalibrateSpeed(
6278 IN gckHARDWARE Hardware,
6283 gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Idle=%u Time=%u",
6284 Os, Hardware, Idle, Time);
6286 /* Do whatever you need to do to callibrate the GPU speed. */
6290 return gcvSTATUS_OK;
6293 /*******************************************************************************
6294 ********************************** Semaphores **********************************
6295 *******************************************************************************/
6297 /*******************************************************************************
6299 ** gckOS_CreateSemaphore
6301 ** Create a semaphore.
6306 ** Pointer to the gckOS object.
6310 ** gctPOINTER * Semaphore
6311 ** Pointer to the variable that will receive the created semaphore.
6314 gckOS_CreateSemaphore(
6316 OUT gctPOINTER * Semaphore
6320 struct semaphore *sem = gcvNULL;
6322 gcmkHEADER_ARG("Os=0x%X", Os);
6324 /* Verify the arguments. */
6325 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6326 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6328 /* Allocate the semaphore structure. */
6329 sem = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
6332 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6335 /* Initialize the semaphore. */
6338 /* Return to caller. */
6339 *Semaphore = (gctPOINTER) sem;
6343 return gcvSTATUS_OK;
6346 /* Return the status. */
6351 /*******************************************************************************
6353 ** gckOS_AcquireSemaphore
6355 ** Acquire a semaphore.
6360 ** Pointer to the gckOS object.
6362 ** gctPOINTER Semaphore
6363 ** Pointer to the semaphore thet needs to be acquired.
6370 gckOS_AcquireSemaphore(
6372 IN gctPOINTER Semaphore
6377 gcmkHEADER_ARG("Os=0x%08X Semaphore=0x%08X", Os, Semaphore);
6379 /* Verify the arguments. */
6380 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6381 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6383 /* Acquire the semaphore. */
6384 if (down_interruptible((struct semaphore *) Semaphore))
6386 gcmkONERROR(gcvSTATUS_INTERRUPTED);
6391 return gcvSTATUS_OK;
6394 /* Return the status. */
6399 /*******************************************************************************
6401 ** gckOS_TryAcquireSemaphore
6403 ** Try to acquire a semaphore.
6408 ** Pointer to the gckOS object.
6410 ** gctPOINTER Semaphore
6411 ** Pointer to the semaphore thet needs to be acquired.
6418 gckOS_TryAcquireSemaphore(
6420 IN gctPOINTER Semaphore
6425 gcmkHEADER_ARG("Os=0x%x", Os);
6427 /* Verify the arguments. */
6428 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6429 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6431 /* Acquire the semaphore. */
6432 if (down_trylock((struct semaphore *) Semaphore))
6435 status = gcvSTATUS_TIMEOUT;
6442 return gcvSTATUS_OK;
6445 /*******************************************************************************
6447 ** gckOS_ReleaseSemaphore
6449 ** Release a previously acquired semaphore.
6454 ** Pointer to the gckOS object.
6456 ** gctPOINTER Semaphore
6457 ** Pointer to the semaphore thet needs to be released.
6464 gckOS_ReleaseSemaphore(
6466 IN gctPOINTER Semaphore
6469 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6471 /* Verify the arguments. */
6472 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6473 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6475 /* Release the semaphore. */
6476 up((struct semaphore *) Semaphore);
6480 return gcvSTATUS_OK;
6483 /*******************************************************************************
6485 ** gckOS_DestroySemaphore
6487 ** Destroy a semaphore.
6492 ** Pointer to the gckOS object.
6494 ** gctPOINTER Semaphore
6495 ** Pointer to the semaphore thet needs to be destroyed.
6502 gckOS_DestroySemaphore(
6504 IN gctPOINTER Semaphore
6507 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%X", Os, Semaphore);
6509 /* Verify the arguments. */
6510 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6511 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
6513 /* Free the sempahore structure. */
6518 return gcvSTATUS_OK;
6521 /*******************************************************************************
6523 ** gckOS_GetProcessID
6525 ** Get current process ID.
6533 ** gctUINT32_PTR ProcessID
6534 ** Pointer to the variable that receives the process ID.
6538 OUT gctUINT32_PTR ProcessID
6541 /* Get process ID. */
6542 if (ProcessID != gcvNULL)
6544 *ProcessID = _GetProcessID();
6548 return gcvSTATUS_OK;
6551 /*******************************************************************************
6553 ** gckOS_GetThreadID
6555 ** Get current thread ID.
6563 ** gctUINT32_PTR ThreadID
6564 ** Pointer to the variable that receives the thread ID.
6568 OUT gctUINT32_PTR ThreadID
6571 /* Get thread ID. */
6572 if (ThreadID != gcvNULL)
6574 *ThreadID = _GetThreadID();
6578 return gcvSTATUS_OK;
6581 /*******************************************************************************
6583 ** gckOS_SetGPUPower
6585 ** Set the power of the GPU on or off.
6590 ** Pointer to a gckOS object.
6593 ** GPU whose power is set.
6596 ** gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
6599 ** gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
6613 gcsPLATFORM * platform;
6615 gctBOOL powerChange = gcvFALSE;
6616 gctBOOL clockChange = gcvFALSE;
6618 gcmkHEADER_ARG("Os=0x%X Core=%d Clock=%d Power=%d", Os, Core, Clock, Power);
6619 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6621 platform = Os->device->platform;
6623 powerChange = (Power != Os->powerStates[Core]);
6625 clockChange = (Clock != Os->clockStates[Core]);
6627 if (powerChange && (Power == gcvTRUE))
6629 if (platform && platform->ops->setPower)
6631 gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
6634 Os->powerStates[Core] = Power;
6639 mutex_lock(&Os->registerAccessLocks[Core]);
6641 if (platform && platform->ops->setClock)
6643 gcmkVERIFY_OK(platform->ops->setClock(platform, Core, Clock));
6646 Os->clockStates[Core] = Clock;
6648 mutex_unlock(&Os->registerAccessLocks[Core]);
6651 if (powerChange && (Power == gcvFALSE))
6653 if (platform && platform->ops->setPower)
6655 gcmkVERIFY_OK(platform->ops->setPower(platform, Core, Power));
6658 Os->powerStates[Core] = Power;
6662 return gcvSTATUS_OK;
6665 /*******************************************************************************
6674 ** Pointer to a gckOS object.
6677 ** GPU whose power is set.
6689 gceSTATUS status = gcvSTATUS_NOT_SUPPORTED;
6690 gcsPLATFORM * platform;
6692 gcmkHEADER_ARG("Os=0x%X Core=%d", Os, Core);
6693 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6695 platform = Os->device->platform;
6697 if (platform && platform->ops->reset)
6699 status = platform->ops->reset(platform, Core);
6706 /*******************************************************************************
6708 ** gckOS_PrepareGPUFrequency
6710 ** Prepare to set GPU frequency and voltage.
6715 ** Pointer to a gckOS object.
6718 ** GPU whose frequency and voltage will be set.
6725 gckOS_PrepareGPUFrequency(
6730 return gcvSTATUS_OK;
6733 /*******************************************************************************
6735 ** gckOS_FinishGPUFrequency
6737 ** Finish GPU frequency setting.
6742 ** Pointer to a gckOS object.
6745 ** GPU whose frequency and voltage is set.
6752 gckOS_FinishGPUFrequency(
6757 return gcvSTATUS_OK;
6760 /*******************************************************************************
6762 ** gckOS_QueryGPUFrequency
6764 ** Query the current frequency of the GPU.
6769 ** Pointer to a gckOS object.
6772 ** GPU whose power is set.
6774 ** gctUINT32 * Frequency
6775 ** Pointer to a gctUINT32 to obtain current frequency, in MHz.
6778 ** Pointer to a gctUINT8 to obtain current scale(1 - 64).
6785 gckOS_QueryGPUFrequency(
6788 OUT gctUINT32 * Frequency,
6789 OUT gctUINT8 * Scale
6792 return gcvSTATUS_OK;
6795 /*******************************************************************************
6797 ** gckOS_SetGPUFrequency
6799 ** Set frequency and voltage of the GPU.
6801 ** 1. DVFS manager gives the target scale of full frequency, BSP must find
6802 ** a real frequency according to this scale and board's configure.
6804 ** 2. BSP should find a suitable voltage for this frequency.
6806 ** 3. BSP must make sure setting take effect before this function returns.
6811 ** Pointer to a gckOS object.
6814 ** GPU whose power is set.
6817 ** Target scale of full frequency, range is [1, 64]. 1 means 1/64 of
6818 ** full frequency and 64 means 64/64 of full frequency.
6825 gckOS_SetGPUFrequency(
6831 return gcvSTATUS_OK;
6834 /*----------------------------------------------------------------------------*/
6835 /*----- Profile --------------------------------------------------------------*/
6838 gckOS_GetProfileTick(
6839 OUT gctUINT64_PTR Tick
6842 struct timespec time;
6844 ktime_get_ts(&time);
6846 *Tick = time.tv_nsec + time.tv_sec * 1000000000ULL;
6848 return gcvSTATUS_OK;
6852 gckOS_QueryProfileTickRate(
6853 OUT gctUINT64_PTR TickRate
6856 struct timespec res;
6858 hrtimer_get_res(CLOCK_MONOTONIC, &res);
6860 *TickRate = res.tv_nsec + res.tv_sec * 1000000000ULL;
6862 return gcvSTATUS_OK;
6870 #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23)
6871 return div_u64(Ticks, 1000000);
6873 gctUINT64 rem = Ticks;
6874 gctUINT64 b = 1000000;
6875 gctUINT64 res, d = 1;
6876 gctUINT32 high = rem >> 32;
6878 /* Reduce the thing a bit first */
6880 if (high >= 1000000)
6883 res = (gctUINT64) high << 32;
6884 rem -= (gctUINT64) (high * 1000000) << 32;
6887 while (((gctINT64) b > 0) && (b < rem))
6906 return (gctUINT32) res;
6910 /******************************************************************************\
6911 ******************************* Signal Management ******************************
6912 \******************************************************************************/
6915 #define _GC_OBJ_ZONE gcvZONE_SIGNAL
6917 /*******************************************************************************
6919 ** gckOS_CreateSignal
6921 ** Create a new signal.
6926 ** Pointer to an gckOS object.
6928 ** gctBOOL ManualReset
6929 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
6930 ** order to set the signal to nonsignaled state.
6931 ** If set to gcvFALSE, the signal will automatically be set to
6932 ** nonsignaled state by gckOS_WaitSignal function.
6936 ** gctSIGNAL * Signal
6937 ** Pointer to a variable receiving the created gctSIGNAL.
6942 IN gctBOOL ManualReset,
6943 OUT gctSIGNAL * Signal
6947 gcsSIGNAL_PTR signal;
6949 gcmkHEADER_ARG("Os=0x%X ManualReset=%d", Os, ManualReset);
6951 /* Verify the arguments. */
6952 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
6953 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
6955 /* Create an event structure. */
6956 signal = (gcsSIGNAL_PTR) kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL | gcdNOWARN);
6958 if (signal == gcvNULL)
6960 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
6963 /* Save the process ID. */
6964 signal->process = (gctHANDLE)(gctUINTPTR_T) _GetProcessID();
6965 signal->manualReset = ManualReset;
6966 signal->hardware = gcvNULL;
6967 init_completion(&signal->obj);
6968 atomic_set(&signal->ref, 1);
6970 gcmkONERROR(_AllocateIntegerId(&Os->signalDB, signal, &signal->id));
6972 *Signal = (gctSIGNAL)(gctUINTPTR_T)signal->id;
6974 gcmkFOOTER_ARG("*Signal=0x%X", *Signal);
6975 return gcvSTATUS_OK;
6978 if (signal != gcvNULL)
6988 gckOS_SignalQueryHardware(
6990 IN gctSIGNAL Signal,
6991 OUT gckHARDWARE * Hardware
6995 gcsSIGNAL_PTR signal;
6997 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
6999 /* Verify the arguments. */
7000 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7001 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7002 gcmkVERIFY_ARGUMENT(Hardware != gcvNULL);
7004 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7006 *Hardware = signal->hardware;
7009 return gcvSTATUS_OK;
7016 gckOS_SignalSetHardware(
7018 IN gctSIGNAL Signal,
7019 IN gckHARDWARE Hardware
7023 gcsSIGNAL_PTR signal;
7025 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Hardware=0x%X", Os, Signal, Hardware);
7027 /* Verify the arguments. */
7028 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7029 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7031 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7033 signal->hardware = Hardware;
7036 return gcvSTATUS_OK;
7042 /*******************************************************************************
7044 ** gckOS_DestroySignal
7046 ** Destroy a signal.
7051 ** Pointer to an gckOS object.
7054 ** Pointer to the gctSIGNAL.
7061 gckOS_DestroySignal(
7067 gcsSIGNAL_PTR signal;
7068 gctBOOL acquired = gcvFALSE;
7070 gcmkHEADER_ARG("Os=0x%X Signal=0x%X", Os, Signal);
7072 /* Verify the arguments. */
7073 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7074 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7076 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7079 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7081 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7083 if (atomic_dec_and_test(&signal->ref))
7085 gcmkVERIFY_OK(_DestroyIntegerId(&Os->signalDB, signal->id));
7087 /* Free the sgianl. */
7091 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7092 acquired = gcvFALSE;
7096 return gcvSTATUS_OK;
7101 /* Release the mutex. */
7102 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7109 /*******************************************************************************
7113 ** Set a state of the specified signal.
7118 ** Pointer to an gckOS object.
7121 ** Pointer to the gctSIGNAL.
7124 ** If gcvTRUE, the signal will be set to signaled state.
7125 ** If gcvFALSE, the signal will be set to nonsignaled state.
7134 IN gctSIGNAL Signal,
7139 gcsSIGNAL_PTR signal;
7140 gctBOOL acquired = gcvFALSE;
7142 gcmkHEADER_ARG("Os=0x%X Signal=0x%X State=%d", Os, Signal, State);
7144 /* Verify the arguments. */
7145 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7146 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7148 gcmkONERROR(gckOS_AcquireMutex(Os, Os->signalMutex, gcvINFINITE));
7151 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7153 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7157 /* unbind the signal from hardware. */
7158 signal->hardware = gcvNULL;
7160 /* Set the event to a signaled state. */
7161 complete(&signal->obj);
7165 /* Set the event to an unsignaled state. */
7166 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
7167 reinit_completion(&signal->obj);
7169 INIT_COMPLETION(signal->obj);
7173 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7174 acquired = gcvFALSE;
7178 return gcvSTATUS_OK;
7183 /* Release the mutex. */
7184 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signalMutex));
7195 IN gctHANDLE Process,
7201 struct task_struct * userTask;
7202 struct siginfo info;
7204 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7206 if (userTask != gcvNULL)
7209 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7212 info.si_ptr = (gctPOINTER) Signal;
7214 /* Signals with numbers between 32 and 63 are real-time,
7215 send a real-time signal to the user process. */
7216 result = send_sig_info(48, &info, userTask);
7218 printk("gckOS_SetSignalVG:0x%x\n", result);
7222 status = gcvSTATUS_GENERIC_IO;
7226 "%s(%d): an error has occurred.\n",
7227 __FUNCTION__, __LINE__
7232 status = gcvSTATUS_OK;
7237 status = gcvSTATUS_GENERIC_IO;
7241 "%s(%d): an error has occurred.\n",
7242 __FUNCTION__, __LINE__
7246 /* Return status. */
7251 /*******************************************************************************
7255 ** Set the specified signal which is owned by a process to signaled state.
7260 ** Pointer to an gckOS object.
7263 ** Pointer to the gctSIGNAL.
7265 ** gctHANDLE Process
7266 ** Handle of process owning the signal.
7275 IN gctSIGNAL Signal,
7276 IN gctHANDLE Process
7282 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=%d",
7283 Os, Signal, (gctINT32)(gctUINTPTR_T)Process);
7285 /* Map the signal into kernel space. */
7286 gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
7289 status = gckOS_Signal(Os, signal, gcvTRUE);
7291 /* Unmap the signal */
7292 gcmkVERIFY_OK(gckOS_UnmapSignal(Os, Signal));
7298 /* Return the status. */
7303 /*******************************************************************************
7307 ** Wait for a signal to become signaled.
7312 ** Pointer to an gckOS object.
7315 ** Pointer to the gctSIGNAL.
7318 ** Number of milliseconds to wait.
7319 ** Pass the value of gcvINFINITE for an infinite wait.
7328 IN gctSIGNAL Signal,
7332 gceSTATUS status = gcvSTATUS_OK;
7333 gcsSIGNAL_PTR signal;
7335 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Wait=0x%08X", Os, Signal, Wait);
7337 /* Verify the arguments. */
7338 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7339 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7341 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7343 gcmkASSERT(signal->id == (gctUINT32)(gctUINTPTR_T)Signal);
7347 spin_lock_irq(&signal->obj.wait.lock);
7349 if (signal->obj.done)
7351 if (!signal->manualReset)
7353 signal->obj.done = 0;
7356 status = gcvSTATUS_OK;
7360 status = gcvSTATUS_TIMEOUT;
7364 /* Convert wait to milliseconds. */
7365 long timeout = (Wait == gcvINFINITE)
7366 ? MAX_SCHEDULE_TIMEOUT
7369 DECLARE_WAITQUEUE(wait, current);
7370 wait.flags |= WQ_FLAG_EXCLUSIVE;
7371 __add_wait_queue_tail(&signal->obj.wait, &wait);
7375 if (signal_pending(current))
7377 /* Interrupt received. */
7378 status = gcvSTATUS_INTERRUPTED;
7382 __set_current_state(TASK_INTERRUPTIBLE);
7383 spin_unlock_irq(&signal->obj.wait.lock);
7384 timeout = schedule_timeout(timeout);
7385 spin_lock_irq(&signal->obj.wait.lock);
7387 if (signal->obj.done)
7389 if (!signal->manualReset)
7391 signal->obj.done = 0;
7394 status = gcvSTATUS_OK;
7401 status = gcvSTATUS_TIMEOUT;
7406 __remove_wait_queue(&signal->obj.wait, &wait);
7409 spin_unlock_irq(&signal->obj.wait.lock);
7412 /* Return status. */
7413 gcmkFOOTER_ARG("Signal=0x%X status=%d", Signal, status);
7417 /*******************************************************************************
7421 ** Map a signal in to the current process space.
7426 ** Pointer to an gckOS object.
7429 ** Pointer to tha gctSIGNAL to map.
7431 ** gctHANDLE Process
7432 ** Handle of process owning the signal.
7436 ** gctSIGNAL * MappedSignal
7437 ** Pointer to a variable receiving the mapped gctSIGNAL.
7442 IN gctSIGNAL Signal,
7443 IN gctHANDLE Process,
7444 OUT gctSIGNAL * MappedSignal
7448 gcsSIGNAL_PTR signal;
7449 gcmkHEADER_ARG("Os=0x%X Signal=0x%X Process=0x%X", Os, Signal, Process);
7451 gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
7452 gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
7454 gcmkONERROR(_QueryIntegerId(&Os->signalDB, (gctUINT32)(gctUINTPTR_T)Signal, (gctPOINTER)&signal));
7456 if(atomic_inc_return(&signal->ref) <= 1)
7458 /* The previous value is 0, it has been deleted. */
7459 gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
7462 *MappedSignal = (gctSIGNAL) Signal;
7465 gcmkFOOTER_ARG("*MappedSignal=0x%X", *MappedSignal);
7466 return gcvSTATUS_OK;
7473 /*******************************************************************************
7475 ** gckOS_UnmapSignal
7482 ** Pointer to an gckOS object.
7485 ** Pointer to that gctSIGNAL mapped.
7493 return gckOS_DestroySignal(Os, Signal);
7496 /*******************************************************************************
7498 ** gckOS_CreateUserSignal
7500 ** Create a new signal to be used in the user space.
7505 ** Pointer to an gckOS object.
7507 ** gctBOOL ManualReset
7508 ** If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
7509 ** order to set the signal to nonsignaled state.
7510 ** If set to gcvFALSE, the signal will automatically be set to
7511 ** nonsignaled state by gckOS_WaitSignal function.
7515 ** gctINT * SignalID
7516 ** Pointer to a variable receiving the created signal's ID.
7519 gckOS_CreateUserSignal(
7521 IN gctBOOL ManualReset,
7522 OUT gctINT * SignalID
7528 /* Create a new signal. */
7529 gcmkONERROR(gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
7530 *SignalID = (gctINT) signal;
7536 /*******************************************************************************
7538 ** gckOS_DestroyUserSignal
7540 ** Destroy a signal to be used in the user space.
7545 ** Pointer to an gckOS object.
7555 gckOS_DestroyUserSignal(
7560 return gckOS_DestroySignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID);
7563 /*******************************************************************************
7565 ** gckOS_WaitUserSignal
7567 ** Wait for a signal used in the user mode to become signaled.
7572 ** Pointer to an gckOS object.
7578 ** Number of milliseconds to wait.
7579 ** Pass the value of gcvINFINITE for an infinite wait.
7586 gckOS_WaitUserSignal(
7592 return gckOS_WaitSignal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, Wait);
7595 /*******************************************************************************
7597 ** gckOS_SignalUserSignal
7599 ** Set a state of the specified signal to be used in the user space.
7604 ** Pointer to an gckOS object.
7610 ** If gcvTRUE, the signal will be set to signaled state.
7611 ** If gcvFALSE, the signal will be set to nonsignaled state.
7618 gckOS_SignalUserSignal(
7624 return gckOS_Signal(Os, (gctSIGNAL)(gctUINTPTR_T)SignalID, State);
7629 gckOS_CreateSemaphoreVG(
7631 OUT gctSEMAPHORE * Semaphore
7635 struct semaphore * newSemaphore;
7637 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
7638 /* Verify the arguments. */
7639 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7640 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
7644 /* Allocate the semaphore structure. */
7645 newSemaphore = (struct semaphore *)kmalloc(gcmSIZEOF(struct semaphore), GFP_KERNEL | gcdNOWARN);
7646 if (newSemaphore == gcvNULL)
7648 gcmkERR_BREAK(gcvSTATUS_OUT_OF_MEMORY);
7651 /* Initialize the semaphore. */
7652 sema_init(newSemaphore, 0);
7654 /* Set the handle. */
7655 * Semaphore = (gctSEMAPHORE) newSemaphore;
7658 status = gcvSTATUS_OK;
7663 /* Return the status. */
7669 gckOS_IncrementSemaphore(
7671 IN gctSEMAPHORE Semaphore
7674 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
7675 /* Verify the arguments. */
7676 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7677 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
7679 /* Increment the semaphore's count. */
7680 up((struct semaphore *) Semaphore);
7684 return gcvSTATUS_OK;
7688 gckOS_DecrementSemaphore(
7690 IN gctSEMAPHORE Semaphore
7696 gcmkHEADER_ARG("Os=0x%X Semaphore=0x%x", Os, Semaphore);
7697 /* Verify the arguments. */
7698 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7699 gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
7703 /* Decrement the semaphore's count. If the count is zero, wait
7704 until it gets incremented. */
7705 result = down_interruptible((struct semaphore *) Semaphore);
7707 /* Signal received? */
7710 status = gcvSTATUS_TERMINATE;
7715 status = gcvSTATUS_OK;
7720 /* Return the status. */
7724 /*******************************************************************************
7728 ** Set the specified signal to signaled state.
7733 ** Pointer to the gckOS object.
7735 ** gctHANDLE Process
7736 ** Handle of process owning the signal.
7739 ** Pointer to the gctSIGNAL.
7748 IN gctHANDLE Process,
7754 struct task_struct * userTask;
7755 struct siginfo info;
7757 userTask = FIND_TASK_BY_PID((pid_t)(gctUINTPTR_T) Process);
7759 if (userTask != gcvNULL)
7762 info.si_code = __SI_CODE(__SI_RT, SI_KERNEL);
7765 info.si_ptr = (gctPOINTER) Signal;
7767 /* Signals with numbers between 32 and 63 are real-time,
7768 send a real-time signal to the user process. */
7769 result = send_sig_info(48, &info, userTask);
7774 status = gcvSTATUS_GENERIC_IO;
7778 "%s(%d): an error has occurred.\n",
7779 __FUNCTION__, __LINE__
7784 status = gcvSTATUS_OK;
7789 status = gcvSTATUS_GENERIC_IO;
7793 "%s(%d): an error has occurred.\n",
7794 __FUNCTION__, __LINE__
7798 /* Return status. */
7802 /******************************************************************************\
7803 ******************************** Thread Object *********************************
7804 \******************************************************************************/
7809 IN gctTHREADFUNC ThreadFunction,
7810 IN gctPOINTER ThreadParameter,
7811 OUT gctTHREAD * Thread
7815 struct task_struct * thread;
7817 gcmkHEADER_ARG("Os=0x%X ", Os);
7818 /* Verify the arguments. */
7819 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7820 gcmkVERIFY_ARGUMENT(ThreadFunction != gcvNULL);
7821 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
7825 /* Create the thread. */
7826 thread = kthread_create(
7829 "Vivante Kernel Thread"
7835 status = gcvSTATUS_GENERIC_IO;
7839 /* Start the thread. */
7840 wake_up_process(thread);
7842 /* Set the thread handle. */
7843 * Thread = (gctTHREAD) thread;
7846 status = gcvSTATUS_OK;
7851 /* Return the status. */
7861 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
7862 /* Verify the arguments. */
7863 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7864 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
7866 /* Thread should have already been enabled to terminate. */
7867 kthread_stop((struct task_struct *) Thread);
7871 return gcvSTATUS_OK;
7880 gcmkHEADER_ARG("Os=0x%X Thread=0x%x", Os, Thread);
7881 /* Verify the arguments. */
7882 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7883 gcmkVERIFY_ARGUMENT(Thread != gcvNULL);
7887 return gcvSTATUS_OK;
7891 /******************************************************************************\
7892 ******************************** Software Timer ********************************
7893 \******************************************************************************/
7897 struct work_struct * work
7900 gcsOSTIMER_PTR timer = (gcsOSTIMER_PTR)work;
7902 gctTIMERFUNCTION function = timer->function;
7904 function(timer->data);
7907 /*******************************************************************************
7909 ** gckOS_CreateTimer
7911 ** Create a software timer.
7916 ** Pointer to the gckOS object.
7918 ** gctTIMERFUNCTION Function.
7919 ** Pointer to a call back function which will be called when timer is
7923 ** Private data which will be passed to call back function.
7927 ** gctPOINTER * Timer
7928 ** Pointer to a variable receiving the created timer.
7933 IN gctTIMERFUNCTION Function,
7935 OUT gctPOINTER * Timer
7939 gcsOSTIMER_PTR pointer;
7940 gcmkHEADER_ARG("Os=0x%X Function=0x%X Data=0x%X", Os, Function, Data);
7942 /* Verify the arguments. */
7943 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7944 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
7946 gcmkONERROR(gckOS_Allocate(Os, sizeof(gcsOSTIMER), (gctPOINTER)&pointer));
7948 pointer->function = Function;
7949 pointer->data = Data;
7951 INIT_DELAYED_WORK(&pointer->work, _TimerFunction);
7956 return gcvSTATUS_OK;
7963 /*******************************************************************************
7965 ** gckOS_DestroyTimer
7967 ** Destory a software timer.
7972 ** Pointer to the gckOS object.
7975 ** Pointer to the timer to be destoryed.
7987 gcsOSTIMER_PTR timer;
7988 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
7990 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
7991 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
7993 timer = (gcsOSTIMER_PTR)Timer;
7995 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
7996 cancel_delayed_work_sync(&timer->work);
7998 cancel_delayed_work(&timer->work);
7999 flush_workqueue(Os->workqueue);
8002 gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Os, Timer));
8005 return gcvSTATUS_OK;
8008 /*******************************************************************************
8012 ** Schedule a software timer.
8017 ** Pointer to the gckOS object.
8020 ** Pointer to the timer to be scheduled.
8023 ** Delay in milliseconds.
8032 IN gctPOINTER Timer,
8036 gcsOSTIMER_PTR timer;
8038 gcmkHEADER_ARG("Os=0x%X Timer=0x%X Delay=%u", Os, Timer, Delay);
8040 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8041 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8042 gcmkVERIFY_ARGUMENT(Delay != 0);
8044 timer = (gcsOSTIMER_PTR)Timer;
8046 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3,7,0)
8047 mod_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8049 if (unlikely(delayed_work_pending(&timer->work)))
8051 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,23)
8052 cancel_delayed_work_sync(&timer->work);
8054 cancel_delayed_work(&timer->work);
8055 flush_workqueue(Os->workqueue);
8059 queue_delayed_work(Os->workqueue, &timer->work, msecs_to_jiffies(Delay));
8063 return gcvSTATUS_OK;
8066 /*******************************************************************************
8070 ** Cancel a unscheduled timer.
8075 ** Pointer to the gckOS object.
8078 ** Pointer to the timer to be cancel.
8090 gcsOSTIMER_PTR timer;
8091 gcmkHEADER_ARG("Os=0x%X Timer=0x%X", Os, Timer);
8093 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8094 gcmkVERIFY_ARGUMENT(Timer != gcvNULL);
8096 timer = (gcsOSTIMER_PTR)Timer;
8098 cancel_delayed_work(&timer->work);
8101 return gcvSTATUS_OK;
8105 gckOS_GetProcessNameByPid(
8107 IN gctSIZE_T Length,
8108 OUT gctUINT8_PTR String
8111 struct task_struct *task;
8113 /* Get the task_struct of the task with pid. */
8116 task = FIND_TASK_BY_PID(Pid);
8118 if (task == gcvNULL)
8121 return gcvSTATUS_NOT_FOUND;
8124 /* Get name of process. */
8125 strncpy(String, task->comm, Length);
8129 return gcvSTATUS_OK;
8133 gckOS_DumpCallStack(
8137 gcmkHEADER_ARG("Os=0x%X", Os);
8139 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8144 return gcvSTATUS_OK;
8147 /*******************************************************************************
8149 ** gckOS_DetectProcessByName
8151 ** task->comm maybe part of process name, so this function
8152 ** can only be used for debugging.
8156 ** gctCONST_POINTER Name
8157 ** Pointer to a string to hold name to be check. If the length
8158 ** of name is longer than TASK_COMM_LEN (16), use part of name
8163 ** gcvSTATUS_TRUE if name of current process matches Name.
8167 gckOS_DetectProcessByName(
8168 IN gctCONST_POINTER Name
8171 char comm[sizeof(current->comm)];
8173 memset(comm, 0, sizeof(comm));
8176 gckOS_GetProcessNameByPid(_GetProcessID(), sizeof(current->comm), comm));
8178 return strstr(comm, Name) ? gcvSTATUS_TRUE
8182 #if gcdANDROID_NATIVE_FENCE_SYNC
8185 gckOS_CreateSyncPoint(
8187 OUT gctSYNC_POINT * SyncPoint
8191 gcsSYNC_POINT_PTR syncPoint;
8193 gcmkHEADER_ARG("Os=0x%X", Os);
8195 /* Verify the arguments. */
8196 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8198 /* Create an sync point structure. */
8199 syncPoint = (gcsSYNC_POINT_PTR) kmalloc(
8200 sizeof(gcsSYNC_POINT), GFP_KERNEL | gcdNOWARN);
8202 if (syncPoint == gcvNULL)
8204 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8207 /* Initialize the sync point. */
8208 atomic_set(&syncPoint->ref, 1);
8209 atomic_set(&syncPoint->state, 0);
8211 gcmkONERROR(_AllocateIntegerId(&Os->syncPointDB, syncPoint, &syncPoint->id));
8213 *SyncPoint = (gctSYNC_POINT)(gctUINTPTR_T)syncPoint->id;
8215 gcmkFOOTER_ARG("*SyncPonint=%d", syncPoint->id);
8216 return gcvSTATUS_OK;
8219 if (syncPoint != gcvNULL)
8229 gckOS_ReferenceSyncPoint(
8231 IN gctSYNC_POINT SyncPoint
8235 gcsSYNC_POINT_PTR syncPoint;
8237 gcmkHEADER_ARG("Os=0x%X", Os);
8239 /* Verify the arguments. */
8240 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8241 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8244 _QueryIntegerId(&Os->syncPointDB,
8245 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8246 (gctPOINTER)&syncPoint));
8248 /* Initialize the sync point. */
8249 atomic_inc(&syncPoint->ref);
8252 return gcvSTATUS_OK;
8260 gckOS_DestroySyncPoint(
8262 IN gctSYNC_POINT SyncPoint
8266 gcsSYNC_POINT_PTR syncPoint;
8267 gctBOOL acquired = gcvFALSE;
8269 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8271 /* Verify the arguments. */
8272 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8273 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8275 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8279 _QueryIntegerId(&Os->syncPointDB,
8280 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8281 (gctPOINTER)&syncPoint));
8283 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8285 if (atomic_dec_and_test(&syncPoint->ref))
8287 gcmkVERIFY_OK(_DestroyIntegerId(&Os->syncPointDB, syncPoint->id));
8289 /* Free the sgianl. */
8290 syncPoint->timeline = gcvNULL;
8294 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8295 acquired = gcvFALSE;
8299 return gcvSTATUS_OK;
8304 /* Release the mutex. */
8305 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8313 gckOS_SignalSyncPoint(
8315 IN gctSYNC_POINT SyncPoint
8319 gcsSYNC_POINT_PTR syncPoint;
8320 struct sync_timeline * timeline;
8321 gctBOOL acquired = gcvFALSE;
8323 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8325 /* Verify the arguments. */
8326 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8327 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8329 gcmkONERROR(gckOS_AcquireMutex(Os, Os->syncPointMutex, gcvINFINITE));
8333 _QueryIntegerId(&Os->syncPointDB,
8334 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8335 (gctPOINTER)&syncPoint));
8337 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8339 /* Set signaled state. */
8340 atomic_set(&syncPoint->state, 1);
8342 /* Get parent timeline. */
8343 timeline = syncPoint->timeline;
8345 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8346 acquired = gcvFALSE;
8348 /* Signal timeline. */
8351 sync_timeline_signal(timeline);
8356 return gcvSTATUS_OK;
8361 /* Release the mutex. */
8362 gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->syncPointMutex));
8370 gckOS_QuerySyncPoint(
8372 IN gctSYNC_POINT SyncPoint,
8373 OUT gctBOOL_PTR State
8377 gcsSYNC_POINT_PTR syncPoint;
8379 gcmkHEADER_ARG("Os=0x%X SyncPoint=%d", Os, (gctUINT32)(gctUINTPTR_T)SyncPoint);
8381 /* Verify the arguments. */
8382 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8383 gcmkVERIFY_ARGUMENT(SyncPoint != gcvNULL);
8386 _QueryIntegerId(&Os->syncPointDB,
8387 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8388 (gctPOINTER)&syncPoint));
8390 gcmkASSERT(syncPoint->id == (gctUINT32)(gctUINTPTR_T)SyncPoint);
8393 *State = atomic_read(&syncPoint->state);
8396 gcmkFOOTER_ARG("*State=%d", *State);
8397 return gcvSTATUS_OK;
8405 gckOS_CreateSyncTimeline(
8407 OUT gctHANDLE * Timeline
8410 struct viv_sync_timeline * timeline;
8412 /* Create viv sync timeline. */
8413 timeline = viv_sync_timeline_create("viv timeline", Os);
8415 if (timeline == gcvNULL)
8417 /* Out of memory. */
8418 return gcvSTATUS_OUT_OF_MEMORY;
8421 *Timeline = (gctHANDLE) timeline;
8422 return gcvSTATUS_OK;
8426 gckOS_DestroySyncTimeline(
8428 IN gctHANDLE Timeline
8431 struct viv_sync_timeline * timeline;
8432 gcmkASSERT(Timeline != gcvNULL);
8434 /* Destroy timeline. */
8435 timeline = (struct viv_sync_timeline *) Timeline;
8436 sync_timeline_destroy(&timeline->obj);
8438 return gcvSTATUS_OK;
8442 gckOS_CreateNativeFence(
8444 IN gctHANDLE Timeline,
8445 IN gctSYNC_POINT SyncPoint,
8446 OUT gctINT * FenceFD
8450 struct viv_sync_timeline *timeline;
8451 struct sync_pt * pt = gcvNULL;
8452 struct sync_fence * fence;
8454 gcsSYNC_POINT_PTR syncPoint;
8457 gcmkHEADER_ARG("Os=0x%X Timeline=0x%X SyncPoint=%d",
8458 Os, Timeline, (gctUINT)(gctUINTPTR_T)SyncPoint);
8461 _QueryIntegerId(&Os->syncPointDB,
8462 (gctUINT32)(gctUINTPTR_T)SyncPoint,
8463 (gctPOINTER)&syncPoint));
8465 /* Cast timeline. */
8466 timeline = (struct viv_sync_timeline *) Timeline;
8468 fd = get_unused_fd();
8472 /* Out of resources. */
8473 gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
8476 /* Create viv_sync_pt. */
8477 pt = viv_sync_pt_create(timeline, SyncPoint);
8481 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8484 /* Reference sync_timeline. */
8485 syncPoint->timeline = &timeline->obj;
8487 /* Build fence name. */
8488 snprintf(name, 32, "viv sync_fence-%u", (gctUINT)(gctUINTPTR_T)SyncPoint);
8490 /* Create sync_fence. */
8491 fence = sync_fence_create(name, pt);
8495 gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
8498 /* Install fence to fd. */
8499 sync_fence_install(fence, fd);
8502 gcmkFOOTER_ARG("*FenceFD=%d", fd);
8503 return gcvSTATUS_OK;
8506 /* Error roll back. */
8524 gckOS_AllocatePageArray(
8526 IN gctPHYS_ADDR Physical,
8527 IN gctSIZE_T PageCount,
8528 OUT gctPOINTER * PageArrayLogical,
8529 OUT gctPHYS_ADDR * PageArrayPhysical
8532 gceSTATUS status = gcvSTATUS_OK;
8537 gckALLOCATOR allocator;
8539 gcmkHEADER_ARG("Os=0x%X Physical=0x%X PageCount=%u",
8540 Os, Physical, PageCount);
8542 /* Verify the arguments. */
8543 gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
8544 gcmkVERIFY_ARGUMENT(Physical != gcvNULL);
8545 gcmkVERIFY_ARGUMENT(PageCount > 0);
8547 bytes = PageCount * gcmSIZEOF(gctUINT32);
8548 gcmkONERROR(gckOS_AllocateNonPagedMemory(
8556 table = *PageArrayLogical;
8558 /* Convert pointer to MDL. */
8559 mdl = (PLINUX_MDL)Physical;
8561 allocator = mdl->allocator;
8563 /* Get all the physical addresses and store them in the page table. */
8566 PageCount = PageCount / (PAGE_SIZE / 4096);
8568 /* Try to get the user pages so DMA can happen. */
8569 while (PageCount-- > 0)
8571 unsigned long phys = ~0;
8573 if (mdl->pagedMem && !mdl->contiguous)
8577 gctUINT32 phys_addr;
8578 allocator->ops->Physical(allocator, mdl, offset, &phys_addr);
8579 phys = (unsigned long)phys_addr;
8587 gcvLEVEL_INFO, gcvZONE_OS,
8588 "%s(%d): we should not get this call for Non Paged Memory!",
8589 __FUNCTION__, __LINE__
8593 phys = page_to_phys(nth_page(mdl->u.contiguousPages, offset));
8596 table[offset] = phys;
8603 /* Return the status. */
8610 gckOS_CPUPhysicalToGPUPhysical(
8612 IN gctUINT32 CPUPhysical,
8613 IN gctUINT32_PTR GPUPhysical
8616 gcsPLATFORM * platform;
8617 gcmkHEADER_ARG("CPUPhysical=0x%X", CPUPhysical);
8619 platform = Os->device->platform;
8621 if (platform && platform->ops->getGPUPhysical)
8624 platform->ops->getGPUPhysical(platform, CPUPhysical, GPUPhysical));
8628 *GPUPhysical = CPUPhysical;
8632 return gcvSTATUS_OK;
8636 gckOS_GPUPhysicalToCPUPhysical(
8638 IN gctUINT32 GPUPhysical,
8639 IN gctUINT32_PTR CPUPhysical
8642 gcmkHEADER_ARG("GPUPhysical=0x%X", GPUPhysical);
8644 *CPUPhysical = GPUPhysical;
8647 return gcvSTATUS_OK;
8651 gckOS_PhysicalToPhysicalAddress(
8653 IN gctPOINTER Physical,
8654 OUT gctUINT32 * PhysicalAddress
8657 PLINUX_MDL mdl = (PLINUX_MDL)Physical;
8658 gckALLOCATOR allocator = mdl->allocator;
8662 return allocator->ops->Physical(allocator, mdl, 0, PhysicalAddress);
8665 return gcvSTATUS_NOT_SUPPORTED;
8671 IN gctCONST_STRING Option,
8672 OUT gctUINT32 * Value
8675 gckGALDEVICE device = Os->device;
8677 if (!strcmp(Option, "physBase"))
8679 *Value = device->physBase;
8680 return gcvSTATUS_OK;
8682 else if (!strcmp(Option, "physSize"))
8684 *Value = device->physSize;
8685 return gcvSTATUS_OK;
8687 else if (!strcmp(Option, "mmu"))
8692 *Value = device->mmu;
8694 return gcvSTATUS_OK;
8697 return gcvSTATUS_NOT_SUPPORTED;
8702 struct inode *inode,
8706 gcsFDPRIVATE_PTR private = (gcsFDPRIVATE_PTR)file->private_data;
8708 if (private && private->release)
8710 return private->release(private);
8716 static const struct file_operations fd_fops = {
8717 .release = fd_release,
8723 IN gcsFDPRIVATE_PTR Private,
8727 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
8728 *Fd = anon_inode_getfd(Name, &fd_fops, Private, O_RDWR);
8732 return gcvSTATUS_OUT_OF_RESOURCES;
8735 return gcvSTATUS_OK;
8737 return gcvSTATUS_NOT_SUPPORTED;