gpu: disable the page-alloc-limit of gpu
[firefly-linux-kernel-4.4.55.git] / drivers / staging / rk29 / vivante / hal / os / linux / kernel / gc_hal_kernel_os.c
1 /****************************************************************************
2 *
3 *    Copyright (C) 2005 - 2011 by Vivante Corp.
4 *
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.
9 *
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.
14 *
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.
18 *
19 *****************************************************************************/
20
21
22
23
24 #include "gc_hal_kernel_linux.h"
25
26 #include <linux/pagemap.h>
27 #include <linux/seq_file.h>
28 #include <linux/mm.h>
29 #include <linux/mman.h>
30 #include <linux/sched.h>
31 #include <linux/slab.h>
32 #include <asm/atomic.h>
33 #ifdef NO_DMA_COHERENT
34 #include <linux/dma-mapping.h>
35 #endif /* NO_DMA_COHERENT */
36
37
38 #include <linux/delay.h>
39 #include <mach/pmu.h>
40 #include <mach/cru.h>
41
42 #if !USE_NEW_LINUX_SIGNAL
43 #define USER_SIGNAL_TABLE_LEN_INIT  64
44 #endif
45
46 #define _GC_OBJ_ZONE    gcvZONE_OS
47
48 #define PAGE_ALLOC_LIMIT                    0   // ÏÞÖÆPageÉêÇë
49 #define PAGE_ALLOC_LIMIT_SIZE               0   // ÏÞÖÆPageÉêÇëµÄ´óС,µ¥Î»ÎªM
50
51 #if PAGE_ALLOC_LIMIT
52 int g_pages_alloced = 0;
53 #endif
54
55 #define MEMORY_LOCK(os) \
56     gcmkVERIFY_OK(gckOS_AcquireMutex( \
57                                 (os), \
58                                 (os)->memoryLock, \
59                                 gcvINFINITE))
60
61 #define MEMORY_UNLOCK(os) \
62     gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryLock))
63
64 #define MEMORY_MAP_LOCK(os) \
65     gcmkVERIFY_OK(gckOS_AcquireMutex( \
66                                 (os), \
67                                 (os)->memoryMapLock, \
68                                 gcvINFINITE))
69
70 #define MEMORY_MAP_UNLOCK(os) \
71     gcmkVERIFY_OK(gckOS_ReleaseMutex((os), (os)->memoryMapLock))
72
73 #if gcdkREPORT_VIDMEM_USAGE
74 static gctUINT64  AllocatedSurfaceTotal[12] = {0};
75 /*
76  * AllocatedSurfaceMax[12]: Current total memory
77  * AllocatedSurfaceMax[13]: Current total memory in history
78  */
79 static gctUINT64  AllocatedSurfaceMax[12 + 2] = {0};
80 static char *pszSurfaceType[12] = {"UNKNOWN", "INDEX", "VERTEX", "TEXTURE", "RENDER_TARGET", \
81                                 "DEPTH", "BITMAP", "TILE_STATUS", "MASK", "SCISSOR", "HIERARCHICAL_DEPTH", \
82                                 "NUM_TYPES"};
83 #endif
84
85 /******************************************************************************\
86 ********************************** Structures **********************************
87 \******************************************************************************/
88
89 struct _gckOS
90 {
91     /* Object. */
92     gcsOBJECT                   object;
93
94     /* Heap. */
95     gckHEAP                     heap;
96
97     /* Pointer to device */
98     gckGALDEVICE                device;
99
100     /* Memory management */
101     gctPOINTER                  memoryLock;
102     gctPOINTER                  memoryMapLock;
103
104     struct _LINUX_MDL           *mdlHead;
105     struct _LINUX_MDL           *mdlTail;
106
107     gctUINT32                   baseAddress;
108
109     /* Kernel process ID. */
110     gctUINT32                   kernelProcessID;
111
112 #if !USE_NEW_LINUX_SIGNAL
113     /* Signal management. */
114     struct _signal {
115         /* Unused signal ID number. */
116         gctINT                  unused;
117
118         /* The pointer to the table. */
119         gctPOINTER *            table;
120
121         /* Signal table length. */
122         gctINT                  tableLen;
123
124         /* The current unused signal ID. */
125         gctINT                  currentID;
126
127         /* Lock. */
128         gctPOINTER              lock;
129     } signal;
130 #endif
131 };
132
133 #if !USE_NEW_LINUX_SIGNAL
134 typedef struct _gcsSIGNAL
135 {
136     /* Kernel sync primitive. */
137     struct completion event;
138
139     /* Manual reset flag. */
140     gctBOOL manualReset;
141
142     /* The reference counter. */
143     atomic_t ref;
144
145     /* The owner of the signal. */
146     gctHANDLE process;
147 }
148 gcsSIGNAL;
149
150 typedef struct _gcsSIGNAL * gcsSIGNAL_PTR;
151 #endif
152
153 typedef struct _gcsPageInfo * gcsPageInfo_PTR;
154
155 typedef struct _gcsPageInfo
156 {
157     struct page **pages;
158     gctUINT32_PTR pageTable;
159 }
160 gcsPageInfo;
161
162
163 static PLINUX_MDL
164 _CreateMdl(
165     IN gctINT PID
166     )
167 {
168     PLINUX_MDL  mdl;
169
170     mdl = (PLINUX_MDL)kmalloc(sizeof(struct _LINUX_MDL), GFP_ATOMIC);
171     if (mdl == gcvNULL) return gcvNULL;
172
173     mdl->pid    = PID;
174     mdl->maps   = gcvNULL;
175     mdl->prev   = gcvNULL;
176     mdl->next   = gcvNULL;
177
178     return mdl;
179 }
180
181 static gceSTATUS
182 _DestroyMdlMap(
183     IN PLINUX_MDL Mdl,
184     IN PLINUX_MDL_MAP MdlMap
185     );
186
187 static gceSTATUS
188 _DestroyMdl(
189     IN PLINUX_MDL Mdl
190     )
191 {
192     PLINUX_MDL_MAP mdlMap, next;
193
194     /* Verify the arguments. */
195     gcmkVERIFY_ARGUMENT(Mdl != gcvNULL);
196
197     mdlMap = Mdl->maps;
198
199     while (mdlMap != gcvNULL)
200     {
201         next = mdlMap->next;
202
203         gcmkVERIFY_OK(_DestroyMdlMap(Mdl, mdlMap));
204
205         mdlMap = next;
206     }
207
208     kfree(Mdl);
209
210     return gcvSTATUS_OK;
211 }
212
213 static PLINUX_MDL_MAP
214 _CreateMdlMap(
215     IN PLINUX_MDL Mdl,
216     IN gctINT PID
217     )
218 {
219     PLINUX_MDL_MAP  mdlMap;
220
221     mdlMap = (PLINUX_MDL_MAP)kmalloc(sizeof(struct _LINUX_MDL_MAP), GFP_ATOMIC);
222     if (mdlMap == gcvNULL) return gcvNULL;
223
224     mdlMap->pid     = PID;
225     mdlMap->vmaAddr = gcvNULL;
226     mdlMap->vma     = gcvNULL;
227
228     mdlMap->next    = Mdl->maps;
229     Mdl->maps       = mdlMap;
230
231     return mdlMap;
232 }
233
234 static gceSTATUS
235 _DestroyMdlMap(
236     IN PLINUX_MDL Mdl,
237     IN PLINUX_MDL_MAP MdlMap
238     )
239 {
240     PLINUX_MDL_MAP  prevMdlMap;
241
242     /* Verify the arguments. */
243     gcmkVERIFY_ARGUMENT(MdlMap != gcvNULL);
244     gcmkASSERT(Mdl->maps != gcvNULL);
245
246     if (Mdl->maps == MdlMap)
247     {
248         Mdl->maps = MdlMap->next;
249     }
250     else
251     {
252         prevMdlMap = Mdl->maps;
253
254         while (prevMdlMap->next != MdlMap)
255         {
256             prevMdlMap = prevMdlMap->next;
257
258             gcmkASSERT(prevMdlMap != gcvNULL);
259         }
260
261         prevMdlMap->next = MdlMap->next;
262     }
263
264     kfree(MdlMap);
265
266     return gcvSTATUS_OK;
267 }
268
269 extern PLINUX_MDL_MAP
270 FindMdlMap(
271     IN PLINUX_MDL Mdl,
272     IN gctINT PID
273     )
274 {
275     PLINUX_MDL_MAP  mdlMap;
276
277     mdlMap = Mdl->maps;
278
279     while (mdlMap != gcvNULL)
280     {
281         if (mdlMap->pid == PID) return mdlMap;
282
283         mdlMap = mdlMap->next;
284     }
285
286     return gcvNULL;
287 }
288
289 void
290 FreeProcessMemoryOnExit(
291     IN gckOS Os,
292     IN gckKERNEL Kernel
293     )
294 {
295     PLINUX_MDL      mdl, nextMdl;
296     PLINUX_MDL_MAP  mdlMap;
297
298     MEMORY_LOCK(Os);
299
300     mdl = Os->mdlHead;
301
302     while (mdl != gcvNULL)
303     {
304         if (mdl != Os->mdlTail)
305         {
306             nextMdl = mdl->next;
307         }
308         else
309         {
310             nextMdl = gcvNULL;
311         }
312
313         if (mdl->pagedMem)
314         {
315             mdlMap = mdl->maps;
316
317             if (mdlMap != gcvNULL
318                 && mdlMap->pid == current->tgid
319                 && mdlMap->next == gcvNULL)
320             {
321                 MEMORY_UNLOCK(Os);
322
323                 gcmkVERIFY_OK(gckOS_FreePagedMemory(Os, mdl, mdl->numPages * PAGE_SIZE));
324
325                 MEMORY_LOCK(Os);
326
327                 nextMdl = Os->mdlHead;
328             }
329         }
330
331         mdl = nextMdl;
332     }
333
334     MEMORY_UNLOCK(Os);
335 }
336
337 void
338 PrintInfoOnExit(
339     IN gckOS Os,
340     IN gckKERNEL Kernel
341     )
342 {
343     PLINUX_MDL      mdl, nextMdl;
344     PLINUX_MDL_MAP  mdlMap;
345
346     MEMORY_LOCK(Os);
347
348     mdl = Os->mdlHead;
349
350     while (mdl != gcvNULL)
351     {
352         if (mdl != Os->mdlTail)
353         {
354             nextMdl = mdl->next;
355         }
356         else
357         {
358             nextMdl = gcvNULL;
359         }
360
361         printk("Unfreed mdl: %p, pid: %d -> pagedMem: %s, addr: %p, dmaHandle: 0x%x, pages: %d",
362             mdl,
363             mdl->pid,
364             mdl->pagedMem? "true" : "false",
365             mdl->addr,
366             mdl->dmaHandle,
367             mdl->numPages);
368
369         mdlMap = mdl->maps;
370
371         while (mdlMap != gcvNULL)
372         {
373             printk("\tmap: %p, pid: %d -> vmaAddr: %p, vma: %p",
374                     mdlMap,
375                     mdlMap->pid,
376                     mdlMap->vmaAddr,
377                     mdlMap->vma);
378
379             mdlMap = mdlMap->next;
380         }
381
382         mdl = nextMdl;
383     }
384
385     MEMORY_UNLOCK(Os);
386 }
387
388 void
389 OnProcessExit(
390     IN gckOS Os,
391     IN gckKERNEL Kernel
392     )
393 {
394     /* PrintInfoOnExit(Os, Kernel); */
395
396 #ifdef ANDROID
397     FreeProcessMemoryOnExit(Os, Kernel);
398 #endif
399 }
400
401 /*******************************************************************************
402 **
403 **  gckOS_Construct
404 **
405 **  Construct a new gckOS object.
406 **
407 **  INPUT:
408 **
409 **      gctPOINTER Context
410 **          Pointer to the gckGALDEVICE class.
411 **
412 **  OUTPUT:
413 **
414 **      gckOS * Os
415 **          Pointer to a variable that will hold the pointer to the gckOS object.
416 */
417 gceSTATUS
418 gckOS_Construct(
419     IN gctPOINTER Context,
420     OUT gckOS * Os
421     )
422 {
423     gckOS os;
424     gceSTATUS status;
425
426     /* Verify the arguments. */
427     gcmkVERIFY_ARGUMENT(Os != gcvNULL);
428
429     /* Allocate the gckOS object. */
430     os = (gckOS) kmalloc(gcmSIZEOF(struct _gckOS), GFP_ATOMIC);
431
432     if (os == gcvNULL)
433     {
434         /* Out of memory. */
435         return gcvSTATUS_OUT_OF_MEMORY;
436     }
437
438     /* Zero the memory. */
439     gckOS_ZeroMemory(os, gcmSIZEOF(struct _gckOS));
440
441     /* Initialize the gckOS object. */
442     os->object.type = gcvOBJ_OS;
443
444     /* Set device device. */
445     os->device = Context;
446
447     /* IMPORTANT! No heap yet. */
448     os->heap = gcvNULL;
449
450     /* Initialize the memory lock. */
451     gcmkONERROR(gckOS_CreateMutex(os, &os->memoryLock));
452
453     gcmkONERROR(gckOS_CreateMutex(os, &os->memoryMapLock));
454
455     /* Create the gckHEAP object. */
456     gcmkONERROR(gckHEAP_Construct(os, gcdHEAP_SIZE, &os->heap));
457
458     os->mdlHead = os->mdlTail = gcvNULL;
459
460     /* Find the base address of the physical memory. */
461     os->baseAddress = os->device->baseAddress;
462
463     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
464                   "Physical base address set to 0x%08X.",
465                   os->baseAddress);
466
467     /* Get the kernel process ID. */
468     gcmkONERROR(gckOS_GetProcessID(&os->kernelProcessID));
469
470 #if !USE_NEW_LINUX_SIGNAL
471     /*
472      * Initialize the signal manager.
473      * It creates the signals to be used in
474      * the user space.
475      */
476
477     /* Initialize mutex. */
478     gcmkONERROR(
479         gckOS_CreateMutex(os, &os->signal.lock));
480
481     /* Initialize the signal table. */
482     os->signal.table =
483         kmalloc(gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT, GFP_KERNEL);
484
485     if (os->signal.table == gcvNULL)
486     {
487         /* Out of memory. */
488         status = gcvSTATUS_OUT_OF_MEMORY;
489         goto OnError;
490     }
491
492     gckOS_ZeroMemory(os->signal.table,
493                      gcmSIZEOF(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
494
495     /* Set the signal table length. */
496     os->signal.tableLen = USER_SIGNAL_TABLE_LEN_INIT;
497
498     /* The table is empty. */
499     os->signal.unused = os->signal.tableLen;
500
501     /* Initial signal ID. */
502     os->signal.currentID = 0;
503 #endif
504
505     /* Return pointer to the gckOS object. */
506     *Os = os;
507
508     /* Success. */
509     return gcvSTATUS_OK;
510
511 OnError:
512 #if !USE_NEW_LINUX_SIGNAL
513     /* Roll back any allocation. */
514     if (os->signal.table != gcvNULL)
515     {
516         kfree(os->signal.table);
517     }
518
519     if (os->signal.lock != gcvNULL)
520     {
521         gcmkVERIFY_OK(
522             gckOS_DeleteMutex(os, os->signal.lock));
523     }
524 #endif
525
526     if (os->heap != gcvNULL)
527     {
528         gcmkVERIFY_OK(
529             gckHEAP_Destroy(os->heap));
530     }
531
532     if (os->memoryMapLock != gcvNULL)
533     {
534         gcmkVERIFY_OK(
535             gckOS_DeleteMutex(os, os->memoryMapLock));
536     }
537
538     if (os->memoryLock != gcvNULL)
539     {
540         gcmkVERIFY_OK(
541             gckOS_DeleteMutex(os, os->memoryLock));
542     }
543
544     kfree(os);
545
546     /* Return the error. */
547     return status;
548 }
549
550 /*******************************************************************************
551 **
552 **  gckOS_Destroy
553 **
554 **  Destroy an gckOS object.
555 **
556 **  INPUT:
557 **
558 **      gckOS Os
559 **          Pointer to an gckOS object that needs to be destroyed.
560 **
561 **  OUTPUT:
562 **
563 **      Nothing.
564 */
565 gceSTATUS
566 gckOS_Destroy(
567     IN gckOS Os
568     )
569 {
570     gckHEAP heap;
571
572     /* Verify the arguments. */
573     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
574
575 #if !USE_NEW_LINUX_SIGNAL
576     /*
577      * Destroy the signal manager.
578      */
579
580     /* Destroy the mutex. */
581     gcmkVERIFY_OK(
582         gckOS_DeleteMutex(Os, Os->signal.lock));
583
584     /* Free the signal table. */
585     kfree(Os->signal.table);
586 #endif
587
588     if (Os->heap != NULL)
589     {
590         /* Mark gckHEAP as gone. */
591         heap     = Os->heap;
592         Os->heap = NULL;
593
594         /* Destroy the gckHEAP object. */
595         gcmkVERIFY_OK(
596             gckHEAP_Destroy(heap));
597     }
598
599     /* Destroy the memory lock. */
600     gcmkVERIFY_OK(
601         gckOS_DeleteMutex(Os, Os->memoryMapLock));
602
603     gcmkVERIFY_OK(
604         gckOS_DeleteMutex(Os, Os->memoryLock));
605
606     gcmkPRINT("$$FLUSH$$");
607
608     /* Mark the gckOS object as unknown. */
609     Os->object.type = gcvOBJ_UNKNOWN;
610
611     /* Free the gckOS object. */
612     kfree(Os);
613
614     /* Success. */
615     return gcvSTATUS_OK;
616 }
617
618 /*******************************************************************************
619 **
620 **  gckOS_Allocate
621 **
622 **  Allocate memory.
623 **
624 **  INPUT:
625 **
626 **      gckOS Os
627 **          Pointer to an gckOS object.
628 **
629 **      gctSIZE_T Bytes
630 **          Number of bytes to allocate.
631 **
632 **  OUTPUT:
633 **
634 **      gctPOINTER * Memory
635 **          Pointer to a variable that will hold the allocated memory location.
636 */
637 gceSTATUS
638 gckOS_Allocate(
639     IN gckOS Os,
640     IN gctSIZE_T Bytes,
641     OUT gctPOINTER * Memory
642     )
643 {
644     gceSTATUS status;
645
646     //gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
647
648     /* Verify the arguments. */
649     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
650     gcmkVERIFY_ARGUMENT(Bytes > 0);
651     gcmkVERIFY_ARGUMENT(Memory != NULL);
652
653     /* Do we have a heap? */
654     if (Os->heap != NULL)
655     {
656         /* Allocate from the heap. */
657         gcmkONERROR(gckHEAP_Allocate(Os->heap, Bytes, Memory));
658     }
659     else
660     {
661         gcmkONERROR(gckOS_AllocateMemory(Os, Bytes, Memory));
662     }
663
664     /* Success. */
665     //gcmkFOOTER_ARG("*memory=0x%x", *Memory);
666     return gcvSTATUS_OK;
667
668 OnError:
669     /* Return the status. */
670     gcmkFOOTER();
671     return status;
672 }
673
674 /*******************************************************************************
675 **
676 **  gckOS_Free
677 **
678 **  Free allocated memory.
679 **
680 **  INPUT:
681 **
682 **      gckOS Os
683 **          Pointer to an gckOS object.
684 **
685 **      gctPOINTER Memory
686 **          Pointer to memory allocation to free.
687 **
688 **  OUTPUT:
689 **
690 **      Nothing.
691 */
692 gceSTATUS
693 gckOS_Free(
694     IN gckOS Os,
695     IN gctPOINTER Memory
696     )
697 {
698     gceSTATUS status;
699
700     /* Verify the arguments. */
701     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
702     gcmkVERIFY_ARGUMENT(Memory != NULL);
703
704     //gcmkHEADER_ARG("Os=0x%x Memory=0x%x", Os, memory);
705
706     /* Do we have a heap? */
707     if (Os->heap != NULL)
708     {
709         /* Free from the heap. */
710         gcmkONERROR(gckHEAP_Free(Os->heap, Memory));
711     }
712     else
713     {
714         gcmkONERROR(gckOS_FreeMemory(Os, Memory));
715     }
716
717     /* Success. */
718     //gcmkFOOTER_NO();
719     return gcvSTATUS_OK;
720
721 OnError:
722     /* Return the status. */
723     gcmkFOOTER();
724     return status;
725 }
726
727 /*******************************************************************************
728 **
729 **  gckOS_AllocateMemory
730 **
731 **  Allocate memory wrapper.
732 **
733 **  INPUT:
734 **
735 **      gctSIZE_T Bytes
736 **          Number of bytes to allocate.
737 **
738 **  OUTPUT:
739 **
740 **      gctPOINTER * Memory
741 **          Pointer to a variable that will hold the allocated memory location.
742 */
743 gceSTATUS
744 gckOS_AllocateMemory(
745     IN gckOS Os,
746     IN gctSIZE_T Bytes,
747     OUT gctPOINTER * Memory
748     )
749 {
750     gctPOINTER memory;
751     gceSTATUS status;
752
753     gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
754
755     /* Verify the arguments. */
756     gcmkVERIFY_ARGUMENT(Bytes > 0);
757     gcmkVERIFY_ARGUMENT(Memory != NULL);
758
759     memory = (gctPOINTER) kmalloc(Bytes, GFP_ATOMIC);
760
761     if (memory == NULL)
762     {
763         /* Out of memory. */
764         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
765     }
766
767     /* Return pointer to the memory allocation. */
768     *Memory = memory;
769
770     /* Success. */
771     gcmkFOOTER_ARG("*Memory=%p", *Memory);
772     return gcvSTATUS_OK;
773
774 OnError:
775     /* Return the status. */
776     gcmkFOOTER();
777     return status;
778 }
779
780 /*******************************************************************************
781 **
782 **  gckOS_FreeMemory
783 **
784 **  Free allocated memory wrapper.
785 **
786 **  INPUT:
787 **
788 **      gctPOINTER Memory
789 **          Pointer to memory allocation to free.
790 **
791 **  OUTPUT:
792 **
793 **      Nothing.
794 */
795 gceSTATUS
796 gckOS_FreeMemory(
797     IN gckOS Os,
798     IN gctPOINTER Memory
799     )
800 {
801     gcmkHEADER_ARG("Memory=%p", Memory);
802
803     /* Verify the arguments. */
804     gcmkVERIFY_ARGUMENT(Memory != NULL);
805
806     /* Free the memory from the OS pool. */
807     kfree(Memory);
808
809     /* Success. */
810     gcmkFOOTER_NO();
811     return gcvSTATUS_OK;
812 }
813
814 /*******************************************************************************
815 **
816 **  gckOS_AllocateVirtualMemory
817 **
818 **  Allocate virtual memory wrapper.
819 **
820 **  INPUT:
821 **
822 **      gctSIZE_T Bytes
823 **          Number of bytes to allocate.
824 **
825 **  OUTPUT:
826 **
827 **      gctPOINTER * Memory
828 **          Pointer to a variable that will hold the allocated memory location.
829 */
830 gceSTATUS
831 gckOS_AllocateVirtualMemory(
832     IN gckOS Os,
833     IN gctSIZE_T Bytes,
834     OUT gctPOINTER * Memory
835     )
836 {
837     gctPOINTER memory;
838     gceSTATUS status;
839
840     gcmkHEADER_ARG("Os=0x%x Bytes=%lu", Os, Bytes);
841
842     /* Verify the arguments. */
843     gcmkVERIFY_ARGUMENT(Bytes > 0);
844     gcmkVERIFY_ARGUMENT(Memory != NULL);
845
846     memory = (gctPOINTER) vmalloc(Bytes);
847
848     if (memory == NULL)
849     {
850         /* Out of memory. */
851         gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
852     }
853
854     /* Return pointer to the memory allocation. */
855     *Memory = memory;
856
857     /* Success. */
858     gcmkFOOTER_ARG("*Memory=%p", *Memory);
859     return gcvSTATUS_OK;
860
861 OnError:
862     /* Return the status. */
863     gcmkFOOTER();
864     return status;
865 }
866
867 /*******************************************************************************
868 **
869 **  gckOS_FreeVirtualMemory
870 **
871 **  Free allocated virtual memory wrapper.
872 **
873 **  INPUT:
874 **
875 **      gctPOINTER Memory
876 **          Pointer to memory allocation to free.
877 **
878 **  OUTPUT:
879 **
880 **      Nothing.
881 */
882 gceSTATUS
883 gckOS_FreeVirtualMemory(
884     IN gckOS Os,
885     IN gctPOINTER Memory
886     )
887 {
888     gcmkHEADER_ARG("Memory=%p", Memory);
889
890     /* Verify the arguments. */
891     gcmkVERIFY_ARGUMENT(Memory != NULL);
892
893     /* Free the memory from the OS pool. */
894     vfree(Memory);
895
896     /* Success. */
897     gcmkFOOTER_NO();
898     return gcvSTATUS_OK;
899 }
900
901 /*******************************************************************************
902 **
903 **  gckOS_MapMemory
904 **
905 **  Map physical memory into the current process.
906 **
907 **  INPUT:
908 **
909 **      gckOS Os
910 **          Pointer to an gckOS object.
911 **
912 **      gctPHYS_ADDR Physical
913 **          Start of physical address memory.
914 **
915 **      gctSIZE_T Bytes
916 **          Number of bytes to map.
917 **
918 **  OUTPUT:
919 **
920 **      gctPOINTER * Memory
921 **          Pointer to a variable that will hold the logical address of the
922 **          mapped memory.
923 */
924 gceSTATUS
925 gckOS_MapMemory(
926     IN gckOS Os,
927     IN gctPHYS_ADDR Physical,
928     IN gctSIZE_T Bytes,
929     OUT gctPOINTER * Logical
930     )
931 {
932     PLINUX_MDL_MAP  mdlMap;
933     PLINUX_MDL      mdl = (PLINUX_MDL)Physical;
934
935     /* Verify the arguments. */
936     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
937     gcmkVERIFY_ARGUMENT(Physical != 0);
938     gcmkVERIFY_ARGUMENT(Bytes > 0);
939     gcmkVERIFY_ARGUMENT(Logical != NULL);
940
941     MEMORY_LOCK(Os);
942
943     mdlMap = FindMdlMap(mdl, current->tgid);
944
945     if (mdlMap == gcvNULL)
946     {
947         mdlMap = _CreateMdlMap(mdl, current->tgid);
948
949         if (mdlMap == gcvNULL)
950         {
951             MEMORY_UNLOCK(Os);
952
953             return gcvSTATUS_OUT_OF_MEMORY;
954         }
955     }
956
957     if (mdlMap->vmaAddr == gcvNULL)
958     {
959         down_write(&current->mm->mmap_sem);
960
961         mdlMap->vmaAddr = (char *)do_mmap_pgoff(NULL,
962                     0L,
963                     mdl->numPages * PAGE_SIZE,
964                     PROT_READ | PROT_WRITE,
965                     MAP_SHARED,
966                     0);
967
968         if (mdlMap->vmaAddr == gcvNULL)
969         {
970             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
971                 gcvZONE_OS,
972                 "gckOS_MapMemory: do_mmap_pgoff error");
973
974             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
975                 gcvZONE_OS,
976                 "[gckOS_MapMemory] mdl->numPages: %d",
977                 "[gckOS_MapMemory] mdl->vmaAddr: 0x%x",
978                 mdl->numPages,
979                 mdlMap->vmaAddr
980                 );
981
982             up_write(&current->mm->mmap_sem);
983
984             MEMORY_UNLOCK(Os);
985
986             return gcvSTATUS_OUT_OF_MEMORY;
987         }
988
989         mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
990
991         if (!mdlMap->vma)
992         {
993             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
994                     gcvZONE_OS,
995                     "gckOS_MapMemory: find_vma error.");
996
997             mdlMap->vmaAddr = gcvNULL;
998
999             up_write(&current->mm->mmap_sem);
1000
1001             MEMORY_UNLOCK(Os);
1002
1003             return gcvSTATUS_OUT_OF_RESOURCES;
1004         }
1005
1006 #ifndef NO_DMA_COHERENT
1007         if (dma_mmap_coherent(NULL,
1008                     mdlMap->vma,
1009                     mdl->addr,
1010                     mdl->dmaHandle,
1011                     mdl->numPages * PAGE_SIZE) < 0)
1012         {
1013             up_write(&current->mm->mmap_sem);
1014
1015             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
1016                     gcvZONE_OS,
1017                     "gckOS_MapMemory: dma_mmap_coherent error.");
1018
1019             mdlMap->vmaAddr = gcvNULL;
1020
1021             MEMORY_UNLOCK(Os);
1022
1023             return gcvSTATUS_OUT_OF_RESOURCES;
1024         }
1025 #else
1026
1027 #if (2==gcdENABLE_MEM_CACHE)
1028         mdlMap->vma->vm_page_prot = pgprot_writecombine(mdlMap->vma->vm_page_prot);
1029 #elif (1==gcdENABLE_MEM_CACHE)
1030     // NULL
1031 #else
1032         mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
1033 #endif
1034         mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
1035         mdlMap->vma->vm_pgoff = 0;
1036
1037         if (remap_pfn_range(mdlMap->vma,
1038                             mdlMap->vma->vm_start,
1039                             mdl->dmaHandle >> PAGE_SHIFT,
1040                             mdl->numPages*PAGE_SIZE,
1041                             mdlMap->vma->vm_page_prot) < 0)
1042         {
1043             up_write(&current->mm->mmap_sem);
1044
1045             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
1046                     gcvZONE_OS,
1047                     "gckOS_MapMemory: remap_pfn_range error.");
1048
1049             mdlMap->vmaAddr = gcvNULL;
1050
1051             MEMORY_UNLOCK(Os);
1052
1053             return gcvSTATUS_OUT_OF_RESOURCES;
1054         }
1055 #endif
1056
1057         up_write(&current->mm->mmap_sem);
1058     }
1059
1060     MEMORY_UNLOCK(Os);
1061
1062     *Logical = mdlMap->vmaAddr;
1063
1064     gcmkTRACE_ZONE(gcvLEVEL_ERROR, gcvZONE_OS,
1065                 "gckOS_MapMemory: User Mapped address for 0x%x is 0x%x pid->%d",
1066                 (gctUINT32)mdl->addr,
1067                 (gctUINT32)*Logical,
1068                 mdlMap->pid);
1069
1070     return gcvSTATUS_OK;
1071 }
1072
1073 /*******************************************************************************
1074 **
1075 **  gckOS_UnmapMemory
1076 **
1077 **  Unmap physical memory out of the current process.
1078 **
1079 **  INPUT:
1080 **
1081 **      gckOS Os
1082 **          Pointer to an gckOS object.
1083 **
1084 **      gctPHYS_ADDR Physical
1085 **          Start of physical address memory.
1086 **
1087 **      gctSIZE_T Bytes
1088 **          Number of bytes to unmap.
1089 **
1090 **      gctPOINTER Memory
1091 **          Pointer to a previously mapped memory region.
1092 **
1093 **  OUTPUT:
1094 **
1095 **      Nothing.
1096 */
1097 gceSTATUS
1098 gckOS_UnmapMemory(
1099     IN gckOS Os,
1100     IN gctPHYS_ADDR Physical,
1101     IN gctSIZE_T Bytes,
1102     IN gctPOINTER Logical
1103     )
1104 {
1105     PLINUX_MDL_MAP          mdlMap;
1106     PLINUX_MDL              mdl = (PLINUX_MDL)Physical;
1107     struct task_struct *    task;
1108     struct mm_struct *      mm;
1109
1110     /* Verify the arguments. */
1111     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1112     gcmkVERIFY_ARGUMENT(Physical != 0);
1113     gcmkVERIFY_ARGUMENT(Bytes > 0);
1114     gcmkVERIFY_ARGUMENT(Logical != NULL);
1115
1116     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1117                 gcvZONE_OS,
1118                 "in gckOS_UnmapMemory");
1119
1120     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1121                 gcvZONE_OS,
1122                 "gckOS_UnmapMemory Will be unmapping 0x%x mdl->0x%x",
1123                 (gctUINT32)Logical,
1124                 (gctUINT32)mdl);
1125
1126     MEMORY_LOCK(Os);
1127
1128     if (Logical)
1129     {
1130         gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
1131             gcvZONE_OS,
1132             "[gckOS_UnmapMemory] Logical: 0x%x",
1133             Logical
1134             );
1135
1136         mdlMap = FindMdlMap(mdl, current->tgid);
1137
1138         if (mdlMap == gcvNULL || mdlMap->vmaAddr == gcvNULL)
1139         {
1140             MEMORY_UNLOCK(Os);
1141
1142             return gcvSTATUS_INVALID_ARGUMENT;
1143         }
1144
1145         /* Get the current pointer for the task with stored pid. */
1146         task = FIND_TASK_BY_PID(mdlMap->pid);
1147         if(task) {
1148             mm = get_task_mm(task);
1149             put_task_struct(task);
1150         } else {
1151             mm = gcvNULL;
1152         }
1153
1154         if (mm)
1155         {
1156             down_write(&mm->mmap_sem);
1157             do_munmap(mm, (unsigned long)Logical, mdl->numPages*PAGE_SIZE);
1158             up_write(&mm->mmap_sem);
1159             mmput(mm);
1160         }
1161         else
1162         {
1163             gcmkTRACE_ZONE(gcvLEVEL_INFO,
1164                         gcvZONE_OS,
1165                         "Can't find the task with pid->%d. No unmapping",
1166                         mdlMap->pid);
1167         }
1168
1169         gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1170     }
1171
1172     MEMORY_UNLOCK(Os);
1173
1174     /* Success. */
1175     return gcvSTATUS_OK;
1176 }
1177
1178 /*******************************************************************************
1179 **
1180 **  gckOS_AllocateNonPagedMemory
1181 **
1182 **  Allocate a number of pages from non-paged memory.
1183 **
1184 **  INPUT:
1185 **
1186 **      gckOS Os
1187 **          Pointer to an gckOS object.
1188 **
1189 **      gctBOOL InUserSpace
1190 **          gcvTRUE if the pages need to be mapped into user space.
1191 **
1192 **      gctSIZE_T * Bytes
1193 **          Pointer to a variable that holds the number of bytes to allocate.
1194 **
1195 **  OUTPUT:
1196 **
1197 **      gctSIZE_T * Bytes
1198 **          Pointer to a variable that hold the number of bytes allocated.
1199 **
1200 **      gctPHYS_ADDR * Physical
1201 **          Pointer to a variable that will hold the physical address of the
1202 **          allocation.
1203 **
1204 **      gctPOINTER * Logical
1205 **          Pointer to a variable that will hold the logical address of the
1206 **          allocation.
1207 */
1208 gceSTATUS
1209 gckOS_AllocateNonPagedMemory(
1210     IN gckOS Os,
1211     IN gctBOOL InUserSpace,
1212     IN OUT gctSIZE_T * Bytes,
1213     OUT gctPHYS_ADDR * Physical,
1214     OUT gctPOINTER * Logical
1215     )
1216 {
1217     gctSIZE_T       bytes;
1218     gctINT          numPages;
1219     PLINUX_MDL      mdl;
1220     PLINUX_MDL_MAP  mdlMap = 0;
1221     gctSTRING       addr;
1222
1223 #ifdef NO_DMA_COHERENT
1224     struct page *   page;
1225     long            size, order;
1226     gctPOINTER      vaddr;
1227 #endif
1228
1229     /* Verify the arguments. */
1230     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1231     gcmkVERIFY_ARGUMENT((Bytes != NULL) && (*Bytes > 0));
1232     gcmkVERIFY_ARGUMENT(Physical != NULL);
1233     gcmkVERIFY_ARGUMENT(Logical != NULL);
1234
1235     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1236                 gcvZONE_OS,
1237                 "in gckOS_AllocateNonPagedMemory");
1238
1239     /* Align number of bytes to page size. */
1240     bytes = gcmALIGN(*Bytes, PAGE_SIZE);
1241
1242     /* Get total number of pages.. */
1243     numPages = GetPageCount(bytes, 0);
1244
1245     /* Allocate mdl+vector structure */
1246     mdl = _CreateMdl(current->tgid);
1247
1248     if (mdl == gcvNULL)
1249     {
1250         return gcvSTATUS_OUT_OF_MEMORY;
1251     }
1252
1253     mdl->pagedMem = 0;
1254     mdl->numPages = numPages;
1255
1256     MEMORY_LOCK(Os);
1257
1258 #ifndef NO_DMA_COHERENT
1259     addr = dma_alloc_coherent(NULL,
1260                 mdl->numPages * PAGE_SIZE,
1261                 &mdl->dmaHandle,
1262                 GFP_ATOMIC);
1263 #else
1264     size    = mdl->numPages * PAGE_SIZE;
1265     order   = get_order(size);
1266     //page    = alloc_pages(GFP_KERNEL | GFP_DMA, order);
1267     page    = alloc_pages(GFP_KERNEL , order);  // dkm modify 110330 ½«GFP_DMAÈ¥µô,±ÜÃâ·ÖÅä²»µ½DMAÄÚ´æ
1268
1269     if (page == gcvNULL)
1270     {
1271         MEMORY_UNLOCK(Os);
1272
1273         return gcvSTATUS_OUT_OF_MEMORY;
1274     }
1275
1276     vaddr           = (gctPOINTER)page_address(page);
1277 #if gcdENABLE_MEM_CACHE
1278     addr            = ioremap_cached(virt_to_phys(vaddr), size);
1279 #else
1280     addr            = ioremap_nocache(virt_to_phys(vaddr), size);
1281 #endif
1282     mdl->dmaHandle  = virt_to_phys(vaddr);
1283     mdl->kaddr      = vaddr;
1284
1285 #if ENABLE_ARM_L2_CACHE
1286     dma_cache_maint(vaddr, size, DMA_FROM_DEVICE);
1287 #endif
1288
1289     while (size > 0)
1290     {
1291         SetPageReserved(virt_to_page(vaddr));
1292
1293         vaddr   += PAGE_SIZE;
1294         size    -= PAGE_SIZE;
1295     }
1296 #endif
1297
1298     if (addr == gcvNULL)
1299     {
1300         gcmkTRACE_ZONE(gcvLEVEL_INFO,
1301                 gcvZONE_OS,
1302                 "galcore: Can't allocate memorry for size->0x%x",
1303                 (gctUINT32)bytes);
1304
1305         gcmkVERIFY_OK(_DestroyMdl(mdl));
1306
1307         MEMORY_UNLOCK(Os);
1308
1309         return gcvSTATUS_OUT_OF_MEMORY;
1310     }
1311
1312     if ((Os->baseAddress & 0x80000000) != (mdl->dmaHandle & 0x80000000))
1313     {
1314         mdl->dmaHandle = (mdl->dmaHandle & ~0x80000000)
1315                        | (Os->baseAddress & 0x80000000);
1316     }
1317
1318     mdl->addr = addr;
1319
1320     /*
1321      * We will not do any mapping from here.
1322      * Mapping will happen from mmap method.
1323      * mdl structure will be used.
1324      */
1325
1326     /* Return allocated memory. */
1327     *Bytes = bytes;
1328     *Physical = (gctPHYS_ADDR) mdl;
1329
1330     if (InUserSpace)
1331     {
1332         mdlMap = _CreateMdlMap(mdl, current->tgid);
1333
1334         if (mdlMap == gcvNULL)
1335         {
1336             gcmkVERIFY_OK(_DestroyMdl(mdl));
1337
1338             MEMORY_UNLOCK(Os);
1339
1340             return gcvSTATUS_OUT_OF_MEMORY;
1341         }
1342
1343         /* Only after mmap this will be valid. */
1344
1345         /* We need to map this to user space. */
1346         down_write(&current->mm->mmap_sem);
1347
1348         mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(gcvNULL,
1349                 0L,
1350                 mdl->numPages * PAGE_SIZE,
1351                 PROT_READ | PROT_WRITE,
1352                 MAP_SHARED,
1353                 0);
1354
1355         if (mdlMap->vmaAddr == gcvNULL)
1356         {
1357             gcmkTRACE_ZONE(gcvLEVEL_INFO,
1358                 gcvZONE_OS,
1359                 "galcore: do_mmap_pgoff error");
1360
1361             up_write(&current->mm->mmap_sem);
1362
1363             gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1364             gcmkVERIFY_OK(_DestroyMdl(mdl));
1365
1366             MEMORY_UNLOCK(Os);
1367
1368             return gcvSTATUS_OUT_OF_MEMORY;
1369         }
1370
1371         mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
1372
1373         if (mdlMap->vma == gcvNULL)
1374         {
1375             gcmkTRACE_ZONE(gcvLEVEL_INFO,
1376                 gcvZONE_OS,
1377                 "find_vma error");
1378
1379             up_write(&current->mm->mmap_sem);
1380
1381             gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1382             gcmkVERIFY_OK(_DestroyMdl(mdl));
1383
1384             MEMORY_UNLOCK(Os);
1385
1386             return gcvSTATUS_OUT_OF_RESOURCES;
1387         }
1388
1389 #ifndef NO_DMA_COHERENT
1390         if (dma_mmap_coherent(NULL,
1391                 mdlMap->vma,
1392                 mdl->addr,
1393                 mdl->dmaHandle,
1394                 mdl->numPages * PAGE_SIZE) < 0)
1395         {
1396             up_write(&current->mm->mmap_sem);
1397
1398             gcmkTRACE_ZONE(gcvLEVEL_INFO,
1399                 gcvZONE_OS,
1400                 "dma_mmap_coherent error");
1401
1402             gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1403             gcmkVERIFY_OK(_DestroyMdl(mdl));
1404
1405             MEMORY_UNLOCK(Os);
1406
1407             return gcvSTATUS_OUT_OF_RESOURCES;
1408         }
1409 #else
1410
1411 #if (2==gcdENABLE_MEM_CACHE)
1412         mdlMap->vma->vm_page_prot = pgprot_writecombine(mdlMap->vma->vm_page_prot);
1413 #elif (1==gcdENABLE_MEM_CACHE)
1414         // NULL
1415 #else
1416         mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
1417 #endif
1418         mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
1419         mdlMap->vma->vm_pgoff = 0;
1420
1421         if (remap_pfn_range(mdlMap->vma,
1422                             mdlMap->vma->vm_start,
1423                             mdl->dmaHandle >> PAGE_SHIFT,
1424                             mdl->numPages * PAGE_SIZE,
1425                             mdlMap->vma->vm_page_prot))
1426         {
1427             up_write(&current->mm->mmap_sem);
1428
1429             gcmkTRACE_ZONE(gcvLEVEL_INFO,
1430                     gcvZONE_OS,
1431                     "remap_pfn_range error");
1432
1433             gcmkVERIFY_OK(_DestroyMdlMap(mdl, mdlMap));
1434             gcmkVERIFY_OK(_DestroyMdl(mdl));
1435
1436             MEMORY_UNLOCK(Os);
1437
1438             return gcvSTATUS_OUT_OF_RESOURCES;
1439         }
1440 #endif /* NO_DMA_COHERENT */
1441
1442         up_write(&current->mm->mmap_sem);
1443
1444         *Logical = mdlMap->vmaAddr;
1445     }
1446     else
1447     {
1448         *Logical = (gctPOINTER)mdl->addr;
1449     }
1450
1451     /*
1452      * Add this to a global list.
1453      * Will be used by get physical address
1454      * and mapuser pointer functions.
1455      */
1456
1457     if (!Os->mdlHead)
1458     {
1459         /* Initialize the queue. */
1460         Os->mdlHead = Os->mdlTail = mdl;
1461     }
1462     else
1463     {
1464         /* Add to the tail. */
1465         mdl->prev = Os->mdlTail;
1466         Os->mdlTail->next = mdl;
1467         Os->mdlTail = mdl;
1468     }
1469
1470     MEMORY_UNLOCK(Os);
1471
1472     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1473                 gcvZONE_OS,
1474                 "gckOS_AllocateNonPagedMemory: "
1475                 "Bytes->0x%x, Mdl->%p, Logical->0x%x dmaHandle->0x%x",
1476                 (gctUINT32)bytes,
1477                 mdl,
1478                 (gctUINT32)mdl->addr,
1479                 mdl->dmaHandle);
1480
1481     if (InUserSpace)
1482     {
1483         gcmkTRACE_ZONE(gcvLEVEL_INFO,
1484                 gcvZONE_OS,
1485                 "vmaAddr->0x%x pid->%d",
1486                 (gctUINT32)mdlMap->vmaAddr,
1487                 mdlMap->pid);
1488     }
1489
1490     /* Success. */
1491     return gcvSTATUS_OK;
1492 }
1493
1494 /*******************************************************************************
1495 **
1496 **  gckOS_FreeNonPagedMemory
1497 **
1498 **  Free previously allocated and mapped pages from non-paged memory.
1499 **
1500 **  INPUT:
1501 **
1502 **      gckOS Os
1503 **          Pointer to an gckOS object.
1504 **
1505 **      gctSIZE_T Bytes
1506 **          Number of bytes allocated.
1507 **
1508 **      gctPHYS_ADDR Physical
1509 **          Physical address of the allocated memory.
1510 **
1511 **      gctPOINTER Logical
1512 **          Logical address of the allocated memory.
1513 **
1514 **  OUTPUT:
1515 **
1516 **      Nothing.
1517 */
1518 gceSTATUS gckOS_FreeNonPagedMemory(
1519     IN gckOS Os,
1520     IN gctSIZE_T Bytes,
1521     IN gctPHYS_ADDR Physical,
1522     IN gctPOINTER Logical
1523     )
1524 {
1525     PLINUX_MDL              mdl;
1526     PLINUX_MDL_MAP          mdlMap;
1527     struct task_struct *    task;
1528     struct mm_struct *      mm;
1529
1530 #ifdef NO_DMA_COHERENT
1531     unsigned                size;
1532     gctPOINTER              vaddr;
1533 #endif /* NO_DMA_COHERENT */
1534
1535     /* Verify the arguments. */
1536     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1537     gcmkVERIFY_ARGUMENT(Bytes > 0);
1538     gcmkVERIFY_ARGUMENT(Physical != 0);
1539     gcmkVERIFY_ARGUMENT(Logical != NULL);
1540
1541     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1542                 gcvZONE_OS,
1543                 "in gckOS_FreeNonPagedMemory");
1544
1545     /* Convert physical address into a pointer to a MDL. */
1546     mdl = (PLINUX_MDL) Physical;
1547
1548     MEMORY_LOCK(Os);
1549
1550 #ifndef NO_DMA_COHERENT
1551     dma_free_coherent(gcvNULL,
1552                     mdl->numPages * PAGE_SIZE,
1553                     mdl->addr,
1554                     mdl->dmaHandle);
1555 #else
1556     size    = mdl->numPages * PAGE_SIZE;
1557     vaddr   = mdl->kaddr;
1558
1559     while (size > 0)
1560     {
1561         ClearPageReserved(virt_to_page(vaddr));
1562
1563         vaddr   += PAGE_SIZE;
1564         size    -= PAGE_SIZE;
1565     }
1566
1567     free_pages((unsigned long)mdl->kaddr, get_order(mdl->numPages * PAGE_SIZE));
1568
1569     iounmap(mdl->addr);
1570 #endif /* NO_DMA_COHERENT */
1571
1572     mdlMap = mdl->maps;
1573
1574     while (mdlMap != gcvNULL)
1575     {
1576         if (mdlMap->vmaAddr != gcvNULL)
1577         {
1578             /* Get the current pointer for the task with stored pid. */
1579             task = FIND_TASK_BY_PID(mdlMap->pid);
1580             if(task) {
1581                 mm = get_task_mm(task);
1582                 put_task_struct(task);
1583             } else {
1584                 mm = gcvNULL;
1585             }
1586
1587             if (mm)
1588             {
1589                 down_write(&mm->mmap_sem);
1590
1591                 if (do_munmap(mm,
1592                             (unsigned long)mdlMap->vmaAddr,
1593                             mdl->numPages * PAGE_SIZE) < 0)
1594                 {
1595                     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1596                                 gcvZONE_OS,
1597                                 "gckOS_FreeNonPagedMemory: "
1598                                 "Unmap Failed ->Mdl->0x%x Logical->0x%x vmaAddr->0x%x",
1599                                 (gctUINT32)mdl,
1600                                 (gctUINT32)mdl->addr,
1601                                 (gctUINT32)mdlMap->vmaAddr);
1602                 }
1603
1604                 up_write(&mm->mmap_sem);
1605                 mmput(mm);
1606             }
1607
1608             mdlMap->vmaAddr = gcvNULL;
1609         }
1610
1611         mdlMap = mdlMap->next;
1612     }
1613
1614     /* Remove the node from global list.. */
1615     if (mdl == Os->mdlHead)
1616     {
1617         if ((Os->mdlHead = mdl->next) == gcvNULL)
1618         {
1619             Os->mdlTail = gcvNULL;
1620         }
1621     }
1622     else
1623     {
1624         mdl->prev->next = mdl->next;
1625         if (mdl == Os->mdlTail)
1626         {
1627             Os->mdlTail = mdl->prev;
1628         }
1629         else
1630         {
1631             mdl->next->prev = mdl->prev;
1632         }
1633     }
1634
1635     MEMORY_UNLOCK(Os);
1636
1637     gcmkTRACE_ZONE(gcvLEVEL_INFO,
1638                 gcvZONE_OS,
1639                 "gckOS_FreeNonPagedMemory: "
1640                 "Mdl->0x%x Logical->0x%x",
1641                 (gctUINT32)mdl,
1642                 (gctUINT32)mdl->addr);
1643
1644     gcmkVERIFY_OK(_DestroyMdl(mdl));
1645
1646     /* Success. */
1647     return gcvSTATUS_OK;
1648 }
1649
1650 /*******************************************************************************
1651 **
1652 **  gckOS_ReadRegister
1653 **
1654 **  Read data from a register.
1655 **
1656 **  INPUT:
1657 **
1658 **      gckOS Os
1659 **          Pointer to an gckOS object.
1660 **
1661 **      gctUINT32 Address
1662 **          Address of register.
1663 **
1664 **  OUTPUT:
1665 **
1666 **      gctUINT32 * Data
1667 **          Pointer to a variable that receives the data read from the register.
1668 */
1669 gceSTATUS gckOS_ReadRegister(
1670     IN gckOS Os,
1671     IN gctUINT32 Address,
1672     OUT gctUINT32 * Data
1673     )
1674 {
1675     /* Verify the arguments. */
1676     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1677     gcmkVERIFY_ARGUMENT(Data != NULL);
1678
1679     *Data = readl((gctUINT8 *)Os->device->registerBase + Address);
1680
1681     /* Success. */
1682     return gcvSTATUS_OK;
1683 }
1684
1685 /*******************************************************************************
1686 **
1687 **  gckOS_WriteRegister
1688 **
1689 **  Write data to a register.
1690 **
1691 **  INPUT:
1692 **
1693 **      gckOS Os
1694 **          Pointer to an gckOS object.
1695 **
1696 **      gctUINT32 Address
1697 **          Address of register.
1698 **
1699 **      gctUINT32 Data
1700 **          Data for register.
1701 **
1702 **  OUTPUT:
1703 **
1704 **      Nothing.
1705 */
1706 gceSTATUS gckOS_WriteRegister(
1707     IN gckOS Os,
1708     IN gctUINT32 Address,
1709     IN gctUINT32 Data
1710     )
1711 {
1712     writel(Data, (gctUINT8 *)Os->device->registerBase + Address);
1713
1714     /* Success. */
1715     return gcvSTATUS_OK;
1716 }
1717
1718 /*******************************************************************************
1719 **
1720 **  gckOS_GetPageSize
1721 **
1722 **  Get the system's page size.
1723 **
1724 **  INPUT:
1725 **
1726 **      gckOS Os
1727 **          Pointer to an gckOS object.
1728 **
1729 **  OUTPUT:
1730 **
1731 **      gctSIZE_T * PageSize
1732 **          Pointer to a variable that will receive the system's page size.
1733 */
1734 gceSTATUS gckOS_GetPageSize(
1735     IN gckOS Os,
1736     OUT gctSIZE_T * PageSize
1737     )
1738 {
1739     /* Verify the arguments. */
1740     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1741     gcmkVERIFY_ARGUMENT(PageSize != NULL);
1742
1743     /* Return the page size. */
1744     *PageSize = (gctSIZE_T) PAGE_SIZE;
1745
1746     /* Success. */
1747     return gcvSTATUS_OK;
1748 }
1749
1750 /*******************************************************************************
1751 **
1752 **  gckOS_GetPhysicalAddressProcess
1753 **
1754 **  Get the physical system address of a corresponding virtual address for a
1755 **  given process.
1756 **
1757 **  INPUT:
1758 **
1759 **      gckOS Os
1760 **          Pointer to an gckOS object.
1761 **
1762 **      gctPOINTER Logical
1763 **          Logical address.
1764 **
1765 **      gctUINT ProcessID
1766 **          Procedd ID.
1767 **
1768 **  OUTPUT:
1769 **
1770 **      gctUINT32 * Address
1771 **          Poinetr to a variable that receives the 32-bit physical adress.
1772 */
1773 gceSTATUS
1774 gckOS_GetPhysicalAddressProcess(
1775     IN gckOS Os,
1776     IN gctPOINTER Logical,
1777     IN gctUINT ProcessID,
1778     OUT gctUINT32 * Address
1779     )
1780 {
1781     return gckOS_GetPhysicalAddress(Os, Logical, Address);
1782 }
1783
1784 /*******************************************************************************
1785 **
1786 **  gckOS_GetPhysicalAddress
1787 **
1788 **  Get the physical system address of a corresponding virtual address.
1789 **
1790 **  INPUT:
1791 **
1792 **      gckOS Os
1793 **          Pointer to an gckOS object.
1794 **
1795 **      gctPOINTER Logical
1796 **          Logical address.
1797 **
1798 **  OUTPUT:
1799 **
1800 **      gctUINT32 * Address
1801 **          Poinetr to a variable that receives the 32-bit physical adress.
1802 */
1803 gceSTATUS gckOS_GetPhysicalAddress(
1804     IN gckOS Os,
1805     IN gctPOINTER Logical,
1806     OUT gctUINT32 * Address
1807     )
1808 {
1809     PLINUX_MDL      mdl;
1810     PLINUX_MDL_MAP  mdlMap;
1811
1812     /* Verify the arguments. */
1813     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1814     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1815
1816     /*
1817      * Try to search the address in our list.
1818      * This could be an mmaped memory.
1819       * Search in our list.
1820       */
1821
1822     MEMORY_LOCK(Os);
1823
1824     mdl = Os->mdlHead;
1825
1826     while (mdl != gcvNULL)
1827     {
1828         /* Check for the logical address match. */
1829         if (mdl->addr
1830             && (gctUINT32)Logical >= (gctUINT32)mdl->addr
1831             && (gctUINT32)Logical < ((gctUINT32)mdl->addr + mdl->numPages*PAGE_SIZE))
1832         {
1833             if (mdl->dmaHandle)
1834             {
1835                 /* The memory was from coherent area. */
1836                 *Address = (gctUINT32)mdl->dmaHandle
1837                             + (gctUINT32)((gctUINT32)Logical - (gctUINT32)mdl->addr);
1838             }
1839             else if (mdl->pagedMem)
1840             {
1841                 if (mdl->contiguous)
1842                 {
1843                     *Address = (gctUINT32)virt_to_phys(mdl->addr)
1844                                 + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
1845                 }
1846                 else
1847                 {
1848                     *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
1849                                 + ((gctUINT32)Logical - (gctUINT32)mdl->addr)));
1850                 }
1851             }
1852             else
1853             {
1854                 *Address = (gctUINT32)virt_to_phys(mdl->addr)
1855                             + ((gctUINT32)Logical - (gctUINT32)mdl->addr);
1856             }
1857             break;
1858         }
1859
1860         mdlMap = FindMdlMap(mdl, current->tgid);
1861
1862         /* Is the given address within that range. */
1863         if (mdlMap != gcvNULL
1864             && mdlMap->vmaAddr != gcvNULL
1865             && Logical >= mdlMap->vmaAddr
1866             && Logical < (mdlMap->vmaAddr + mdl->numPages * PAGE_SIZE))
1867         {
1868             if (mdl->dmaHandle)
1869             {
1870                 /* The memory was from coherent area. */
1871                 *Address = (gctUINT32)mdl->dmaHandle
1872                             + (gctUINT32)((gctUINT32)Logical
1873                             - (gctUINT32)mdlMap->vmaAddr);
1874             }
1875             else if (mdl->pagedMem)
1876             {
1877                 if (mdl->contiguous)
1878                 {
1879                     *Address = (gctUINT32)virt_to_phys(mdl->addr)
1880                                 + (gctUINT32)(Logical - mdlMap->vmaAddr);
1881                 }
1882                 else
1883                 {
1884                     *Address = page_to_phys(vmalloc_to_page((gctSTRING)mdl->addr
1885                                 + ((gctUINT32)Logical - (gctUINT32)mdlMap->vmaAddr)));
1886                 }
1887             }
1888             else
1889             {
1890                 /* Return the kernel virtual pointer based on this. */
1891                 *Address = (gctUINT32)virt_to_phys(mdl->addr)
1892                             + (gctUINT32)(Logical - mdlMap->vmaAddr);
1893             }
1894             break;
1895         }
1896
1897         mdl = mdl->next;
1898     }
1899
1900     /* Subtract base address to get a GPU physical address. */
1901     gcmkASSERT(*Address >= Os->baseAddress);
1902     *Address -= Os->baseAddress;
1903
1904     MEMORY_UNLOCK(Os);
1905
1906     if (mdl == gcvNULL)
1907     {
1908         return gcvSTATUS_INVALID_ARGUMENT;
1909     }
1910
1911     /* Success. */
1912     return gcvSTATUS_OK;
1913 }
1914
1915 /*******************************************************************************
1916 **
1917 **  gckOS_MapPhysical
1918 **
1919 **  Map a physical address into kernel space.
1920 **
1921 **  INPUT:
1922 **
1923 **      gckOS Os
1924 **          Pointer to an gckOS object.
1925 **
1926 **      gctUINT32 Physical
1927 **          Physical address of the memory to map.
1928 **
1929 **      gctSIZE_T Bytes
1930 **          Number of bytes to map.
1931 **
1932 **  OUTPUT:
1933 **
1934 **      gctPOINTER * Logical
1935 **          Pointer to a variable that receives the base address of the mapped
1936 **          memory.
1937 */
1938 gceSTATUS gckOS_MapPhysical(
1939     IN gckOS Os,
1940     IN gctUINT32 Physical,
1941     IN gctSIZE_T Bytes,
1942     OUT gctPOINTER * Logical
1943     )
1944 {
1945     gctPOINTER logical;
1946     PLINUX_MDL mdl;
1947     gctUINT32 physical;
1948
1949     /* Verify the arguments. */
1950     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1951     gcmkVERIFY_ARGUMENT(Bytes > 0);
1952     gcmkVERIFY_ARGUMENT(Logical != gcvNULL);
1953
1954     MEMORY_LOCK(Os);
1955
1956     /* Compute true physical address (before subtraction of the baseAddress). */
1957     physical = Physical + Os->baseAddress;
1958
1959     /* Go through our mapping to see if we know this physical address already. */
1960     mdl = Os->mdlHead;
1961
1962     while (mdl != gcvNULL)
1963     {
1964         if (mdl->dmaHandle != 0)
1965         {
1966             if ((physical >= mdl->dmaHandle)
1967             &&  (physical < mdl->dmaHandle + mdl->numPages * PAGE_SIZE)
1968             )
1969             {
1970                 *Logical = mdl->addr + (physical - mdl->dmaHandle);
1971                 break;
1972             }
1973         }
1974
1975         mdl = mdl->next;
1976     }
1977
1978     if (mdl == gcvNULL)
1979     {
1980         /* Map memory as cached memory. */
1981         request_mem_region(physical, Bytes, "MapRegion");
1982 #if gcdENABLE_MEM_CACHE
1983         logical = (gctPOINTER) ioremap_cached(physical, Bytes);
1984 #else
1985         logical = (gctPOINTER) ioremap_nocache(physical, Bytes);
1986 #endif
1987         if (logical == NULL)
1988         {
1989             gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
1990                           "gckOS_MapMemory: Failed to ioremap");
1991
1992             MEMORY_UNLOCK(Os);
1993
1994             /* Out of resources. */
1995             return gcvSTATUS_OUT_OF_RESOURCES;
1996         }
1997
1998         /* Return pointer to mapped memory. */
1999         *Logical = logical;
2000     }
2001
2002     MEMORY_UNLOCK(Os);
2003
2004     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
2005                   "gckOS_MapPhysical: "
2006                   "Physical->0x%X Bytes->0x%X Logical->0x%X MappingFound->%d",
2007                   (gctUINT32) Physical,
2008                   (gctUINT32) Bytes,
2009                   (gctUINT32) *Logical,
2010                    mdl ? 1 : 0);
2011
2012     /* Success. */
2013     return gcvSTATUS_OK;
2014 }
2015
2016 /*******************************************************************************
2017 **
2018 **  gckOS_UnmapPhysical
2019 **
2020 **  Unmap a previously mapped memory region from kernel memory.
2021 **
2022 **  INPUT:
2023 **
2024 **      gckOS Os
2025 **          Pointer to an gckOS object.
2026 **
2027 **      gctPOINTER Logical
2028 **          Pointer to the base address of the memory to unmap.
2029 **
2030 **      gctSIZE_T Bytes
2031 **          Number of bytes to unmap.
2032 **
2033 **  OUTPUT:
2034 **
2035 **      Nothing.
2036 */
2037 gceSTATUS gckOS_UnmapPhysical(
2038     IN gckOS Os,
2039     IN gctPOINTER Logical,
2040     IN gctSIZE_T Bytes
2041     )
2042 {
2043     PLINUX_MDL  mdl;
2044
2045     /* Verify the arguments. */
2046     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2047     gcmkVERIFY_ARGUMENT(Logical != NULL);
2048     gcmkVERIFY_ARGUMENT(Bytes > 0);
2049
2050     MEMORY_LOCK(Os);
2051
2052     mdl = Os->mdlHead;
2053
2054     while (mdl != gcvNULL)
2055     {
2056         if (mdl->addr != gcvNULL)
2057         {
2058             if (Logical >= (gctPOINTER)mdl->addr
2059                     && Logical < (gctPOINTER)((gctSTRING)mdl->addr + mdl->numPages * PAGE_SIZE))
2060             {
2061                 break;
2062             }
2063         }
2064
2065         mdl = mdl->next;
2066     }
2067
2068     if (mdl == gcvNULL)
2069     {
2070         /* Unmap the memory. */
2071         iounmap(Logical);
2072     }
2073
2074     MEMORY_UNLOCK(Os);
2075
2076     gcmkTRACE_ZONE(gcvLEVEL_INFO,
2077                     gcvZONE_OS,
2078                     "gckOS_UnmapPhysical: "
2079                     "Logical->0x%x Bytes->0x%x MappingFound(?)->%d",
2080                     (gctUINT32)Logical,
2081                     (gctUINT32)Bytes,
2082                     mdl ? 1 : 0);
2083
2084     /* Success. */
2085     return gcvSTATUS_OK;
2086 }
2087
2088 /*******************************************************************************
2089 **
2090 **  gckOS_CreateMutex
2091 **
2092 **  Create a new mutex.
2093 **
2094 **  INPUT:
2095 **
2096 **      gckOS Os
2097 **          Pointer to an gckOS object.
2098 **
2099 **  OUTPUT:
2100 **
2101 **      gctPOINTER * Mutex
2102 **          Pointer to a variable that will hold a pointer to the mutex.
2103 */
2104 gceSTATUS gckOS_CreateMutex(
2105     IN gckOS Os,
2106     OUT gctPOINTER * Mutex
2107     )
2108 {
2109     /* Validate the arguments. */
2110     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2111     gcmkVERIFY_ARGUMENT(Mutex != NULL);
2112
2113     /* Allocate a FAST_MUTEX structure. */
2114     *Mutex = (gctPOINTER)kmalloc(sizeof(struct semaphore), GFP_KERNEL);
2115
2116     if (*Mutex == gcvNULL)
2117     {
2118         return gcvSTATUS_OUT_OF_MEMORY;
2119     }
2120
2121     /* Initialize the semaphore.. Come up in unlocked state. */
2122     init_MUTEX(*Mutex);
2123
2124     /* Return status. */
2125     return gcvSTATUS_OK;
2126 }
2127
2128 /*******************************************************************************
2129 **
2130 **  gckOS_DeleteMutex
2131 **
2132 **  Delete a mutex.
2133 **
2134 **  INPUT:
2135 **
2136 **      gckOS Os
2137 **          Pointer to an gckOS object.
2138 **
2139 **      gctPOINTER Mutex
2140 **          Pointer to the mute to be deleted.
2141 **
2142 **  OUTPUT:
2143 **
2144 **      Nothing.
2145 */
2146 gceSTATUS gckOS_DeleteMutex(
2147     IN gckOS Os,
2148     IN gctPOINTER Mutex
2149     )
2150 {
2151     /* Validate the arguments. */
2152     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2153     gcmkVERIFY_ARGUMENT(Mutex != NULL);
2154
2155     /* Delete the fast mutex. */
2156     kfree(Mutex);
2157
2158     return gcvSTATUS_OK;
2159 }
2160
2161 /*******************************************************************************
2162 **
2163 **  gckOS_AcquireMutex
2164 **
2165 **  Acquire a mutex.
2166 **
2167 **  INPUT:
2168 **
2169 **      gckOS Os
2170 **          Pointer to an gckOS object.
2171 **
2172 **      gctPOINTER Mutex
2173 **          Pointer to the mutex to be acquired.
2174 **
2175 **      gctUINT32 Timeout
2176 **          Timeout value specified in milliseconds.
2177 **          Specify the value of gcvINFINITE to keep the thread suspended
2178 **          until the mutex has been acquired.
2179 **
2180 **  OUTPUT:
2181 **
2182 **      Nothing.
2183 */
2184 gceSTATUS
2185 gckOS_AcquireMutex(
2186     IN gckOS Os,
2187     IN gctPOINTER Mutex,
2188     IN gctUINT32 Timeout
2189     )
2190 {
2191     /* Validate the arguments. */
2192     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2193     gcmkVERIFY_ARGUMENT(Mutex != NULL);
2194
2195     if (Timeout == gcvINFINITE)
2196     {
2197         down((struct semaphore *) Mutex);
2198
2199         /* Success. */
2200         return gcvSTATUS_OK;
2201     }
2202
2203     while (gcvTRUE)
2204     {
2205         /* Try to acquire the fast mutex. */
2206         if (!down_trylock((struct semaphore *) Mutex))
2207         {
2208             /* Success. */
2209             return gcvSTATUS_OK;
2210         }
2211
2212                 if (Timeout-- == 0) break;
2213
2214         /* Wait for 1 millisecond. */
2215         gcmkVERIFY_OK(gckOS_Delay(Os, 1));
2216     }
2217
2218     /* Timeout. */
2219     return gcvSTATUS_TIMEOUT;
2220 }
2221
2222 /*******************************************************************************
2223 **
2224 **  gckOS_ReleaseMutex
2225 **
2226 **  Release an acquired mutex.
2227 **
2228 **  INPUT:
2229 **
2230 **      gckOS Os
2231 **          Pointer to an gckOS object.
2232 **
2233 **      gctPOINTER Mutex
2234 **          Pointer to the mutex to be released.
2235 **
2236 **  OUTPUT:
2237 **
2238 **      Nothing.
2239 */
2240 gceSTATUS gckOS_ReleaseMutex(
2241     IN gckOS Os,
2242     IN gctPOINTER Mutex
2243     )
2244 {
2245     /* Validate the arguments. */
2246     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2247     gcmkVERIFY_ARGUMENT(Mutex != NULL);
2248
2249     /* Release the fast mutex. */
2250     up((struct semaphore *) Mutex);
2251
2252     /* Success. */
2253     return gcvSTATUS_OK;
2254 }
2255
2256 /*******************************************************************************
2257 **
2258 **  gckOS_AtomicExchange
2259 **
2260 **  Atomically exchange a pair of 32-bit values.
2261 **
2262 **  INPUT:
2263 **
2264 **      gckOS Os
2265 **          Pointer to an gckOS object.
2266 **
2267 **      IN OUT gctINT32_PTR Target
2268 **          Pointer to the 32-bit value to exchange.
2269 **
2270 **      IN gctINT32 NewValue
2271 **          Specifies a new value for the 32-bit value pointed to by Target.
2272 **
2273 **      OUT gctINT32_PTR OldValue
2274 **          The old value of the 32-bit value pointed to by Target.
2275 **
2276 **  OUTPUT:
2277 **
2278 **      Nothing.
2279 */
2280 gceSTATUS
2281 gckOS_AtomicExchange(
2282     IN gckOS Os,
2283     IN OUT gctUINT32_PTR Target,
2284     IN gctUINT32 NewValue,
2285     OUT gctUINT32_PTR OldValue
2286     )
2287 {
2288     /* Verify the arguments. */
2289     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2290
2291     /* Exchange the pair of 32-bit values. */
2292     *OldValue = (gctUINT32) atomic_xchg((atomic_t *) Target, (int) NewValue);
2293
2294     /* Success. */
2295     return gcvSTATUS_OK;
2296 }
2297
2298 /*******************************************************************************
2299 **
2300 **  gckOS_AtomicExchangePtr
2301 **
2302 **  Atomically exchange a pair of pointers.
2303 **
2304 **  INPUT:
2305 **
2306 **      gckOS Os
2307 **          Pointer to an gckOS object.
2308 **
2309 **      IN OUT gctPOINTER * Target
2310 **          Pointer to the 32-bit value to exchange.
2311 **
2312 **      IN gctPOINTER NewValue
2313 **          Specifies a new value for the pointer pointed to by Target.
2314 **
2315 **      OUT gctPOINTER * OldValue
2316 **          The old value of the pointer pointed to by Target.
2317 **
2318 **  OUTPUT:
2319 **
2320 **      Nothing.
2321 */
2322 gceSTATUS
2323 gckOS_AtomicExchangePtr(
2324     IN gckOS Os,
2325     IN OUT gctPOINTER * Target,
2326     IN gctPOINTER NewValue,
2327     OUT gctPOINTER * OldValue
2328     )
2329 {
2330     /* Verify the arguments. */
2331     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2332
2333     /* Exchange the pair of pointers. */
2334     *OldValue = (gctPOINTER) atomic_xchg((atomic_t *) Target, (int) NewValue);
2335
2336     /* Success. */
2337     return gcvSTATUS_OK;
2338 }
2339
2340 /*******************************************************************************
2341 **
2342 **  gckOS_AtomConstruct
2343 **
2344 **  Create an atom.
2345 **
2346 **  INPUT:
2347 **
2348 **      gckOS Os
2349 **          Pointer to a gckOS object.
2350 **
2351 **  OUTPUT:
2352 **
2353 **      gctPOINTER * Atom
2354 **          Pointer to a variable receiving the constructed atom.
2355 */
2356 gceSTATUS
2357 gckOS_AtomConstruct(
2358     IN gckOS Os,
2359     OUT gctPOINTER * Atom
2360     )
2361 {
2362     gceSTATUS status;
2363
2364     gcmkHEADER_ARG("Os=0x%x", Os);
2365
2366     /* Verify the arguments. */
2367     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2368     gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2369
2370     /* Allocate the atom. */
2371     gcmkONERROR(gckOS_Allocate(Os, gcmSIZEOF(atomic_t), Atom));
2372
2373     /* Initialize the atom. */
2374     atomic_set((atomic_t *) *Atom, 0);
2375
2376     /* Success. */
2377     gcmkFOOTER_ARG("*Atom=0x%x", *Atom);
2378     return gcvSTATUS_OK;
2379
2380 OnError:
2381     /* Return the status. */
2382     gcmkFOOTER();
2383     return status;
2384 }
2385
2386 /*******************************************************************************
2387 **
2388 **  gckOS_AtomDestroy
2389 **
2390 **  Destroy an atom.
2391 **
2392 **  INPUT:
2393 **
2394 **      gckOS Os
2395 **          Pointer to a gckOS object.
2396 **
2397 **      gctPOINTER Atom
2398 **          Pointer to the atom to destroy.
2399 **
2400 **  OUTPUT:
2401 **
2402 **      Nothing.
2403 */
2404 gceSTATUS
2405 gckOS_AtomDestroy(
2406     IN gckOS Os,
2407     OUT gctPOINTER Atom
2408     )
2409 {
2410     gceSTATUS status;
2411
2412     gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2413
2414     /* Verify the arguments. */
2415     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2416     gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2417
2418     /* Free the atom. */
2419     gcmkONERROR(gckOS_Free(Os, Atom));
2420
2421     /* Success. */
2422     gcmkFOOTER_NO();
2423     return gcvSTATUS_OK;
2424
2425 OnError:
2426     /* Return the status. */
2427     gcmkFOOTER();
2428     return status;
2429 }
2430
2431 /*******************************************************************************
2432 **
2433 **  gckOS_AtomGet
2434 **
2435 **  Get the 32-bit value protected by an atom.
2436 **
2437 **  INPUT:
2438 **
2439 **      gckOS Os
2440 **          Pointer to a gckOS object.
2441 **
2442 **      gctPOINTER Atom
2443 **          Pointer to the atom.
2444 **
2445 **  OUTPUT:
2446 **
2447 **      gctINT32_PTR Value
2448 **          Pointer to a variable the receives the value of the atom.
2449 */
2450 gceSTATUS
2451 gckOS_AtomGet(
2452     IN gckOS Os,
2453     IN gctPOINTER Atom,
2454     OUT gctINT32_PTR Value
2455     )
2456 {
2457     gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2458
2459     /* Verify the arguments. */
2460     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2461     gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2462
2463     /* Return the current value of atom. */
2464     *Value = atomic_read((atomic_t *) Atom);
2465
2466     /* Success. */
2467     gcmkFOOTER_ARG("*Value=%d", *Value);
2468     return gcvSTATUS_OK;
2469 }
2470
2471 /*******************************************************************************
2472 **
2473 **  gckOS_AtomIncrement
2474 **
2475 **  Atomically increment the 32-bit integer value inside an atom.
2476 **
2477 **  INPUT:
2478 **
2479 **      gckOS Os
2480 **          Pointer to a gckOS object.
2481 **
2482 **      gctPOINTER Atom
2483 **          Pointer to the atom.
2484 **
2485 **  OUTPUT:
2486 **
2487 **      gctINT32_PTR Value
2488 **          Pointer to a variable the receives the original value of the atom.
2489 */
2490 gceSTATUS
2491 gckOS_AtomIncrement(
2492     IN gckOS Os,
2493     IN gctPOINTER Atom,
2494     OUT gctINT32_PTR Value
2495     )
2496 {
2497     gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2498
2499     /* Verify the arguments. */
2500     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2501     gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2502
2503     /* Increment the atom. */
2504     *Value = atomic_inc_return((atomic_t *) Atom) - 1;
2505
2506     /* Success. */
2507     gcmkFOOTER_ARG("*Value=%d", *Value);
2508     return gcvSTATUS_OK;
2509 }
2510
2511 /*******************************************************************************
2512 **
2513 **  gckOS_AtomDecrement
2514 **
2515 **  Atomically decrement the 32-bit integer value inside an atom.
2516 **
2517 **  INPUT:
2518 **
2519 **      gckOS Os
2520 **          Pointer to a gckOS object.
2521 **
2522 **      gctPOINTER Atom
2523 **          Pointer to the atom.
2524 **
2525 **  OUTPUT:
2526 **
2527 **      gctINT32_PTR Value
2528 **          Pointer to a variable the receives the original value of the atom.
2529 */
2530 gceSTATUS
2531 gckOS_AtomDecrement(
2532     IN gckOS Os,
2533     IN gctPOINTER Atom,
2534     OUT gctINT32_PTR Value
2535     )
2536 {
2537     gcmkHEADER_ARG("Os=0x%x Atom=0x%0x", Os, Atom);
2538
2539     /* Verify the arguments. */
2540     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2541     gcmkVERIFY_ARGUMENT(Atom != gcvNULL);
2542
2543     /* Decrement the atom. */
2544     *Value = atomic_dec_return((atomic_t *) Atom) + 1;
2545
2546     /* Success. */
2547     gcmkFOOTER_ARG("*Value=%d", *Value);
2548     return gcvSTATUS_OK;
2549 }
2550
2551 /*******************************************************************************
2552 **
2553 **  gckOS_Delay
2554 **
2555 **  Delay execution of the current thread for a number of milliseconds.
2556 **
2557 **  INPUT:
2558 **
2559 **      gckOS Os
2560 **          Pointer to an gckOS object.
2561 **
2562 **      gctUINT32 Delay
2563 **          Delay to sleep, specified in milliseconds.
2564 **
2565 **  OUTPUT:
2566 **
2567 **      Nothing.
2568 */
2569 gceSTATUS
2570 gckOS_Delay(
2571     IN gckOS Os,
2572     IN gctUINT32 Delay
2573     )
2574 {
2575     struct timeval now;
2576     unsigned long jiffies;
2577
2578     if (Delay > 0)
2579     {
2580         /* Convert milliseconds into seconds and microseconds. */
2581         now.tv_sec  = Delay / 1000;
2582         now.tv_usec = (Delay % 1000) * 1000;
2583
2584         /* Convert timeval to jiffies. */
2585         jiffies = timeval_to_jiffies(&now);
2586
2587         /* Schedule timeout. */
2588         schedule_timeout_interruptible(jiffies);
2589     }
2590
2591     /* Success. */
2592     return gcvSTATUS_OK;
2593 }
2594
2595 /*******************************************************************************
2596 **
2597 **  gckOS_MemoryBarrier
2598 **
2599 **  Make sure the CPU has executed everything up to this point and the data got
2600 **  written to the specified pointer.
2601 **
2602 **  INPUT:
2603 **
2604 **      gckOS Os
2605 **          Pointer to an gckOS object.
2606 **
2607 **      gctPOINTER Address
2608 **          Address of memory that needs to be barriered.
2609 **
2610 **  OUTPUT:
2611 **
2612 **      Nothing.
2613 */
2614 gceSTATUS gckOS_MemoryBarrier(
2615     IN gckOS Os,
2616     IN gctPOINTER Address
2617     )
2618 {
2619     /* Verify thearguments. */
2620     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2621
2622     //mb();
2623     dsb();
2624
2625     /* Success. */
2626     return gcvSTATUS_OK;
2627 }
2628
2629 /*******************************************************************************
2630 **
2631 **  gckOS_AllocatePagedMemory
2632 **
2633 **  Allocate memory from the paged pool.
2634 **
2635 **  INPUT:
2636 **
2637 **      gckOS Os
2638 **          Pointer to an gckOS object.
2639 **
2640 **      gctSIZE_T Bytes
2641 **          Number of bytes to allocate.
2642 **
2643 **  OUTPUT:
2644 **
2645 **      gctPHYS_ADDR * Physical
2646 **          Pointer to a variable that receives the physical address of the
2647 **          memory allocation.
2648 */
2649 gceSTATUS
2650 gckOS_AllocatePagedMemory(
2651     IN gckOS Os,
2652     IN gctSIZE_T Bytes,
2653     OUT gctPHYS_ADDR * Physical
2654     )
2655 {
2656     return gckOS_AllocatePagedMemoryEx(Os, gcvFALSE, Bytes, Physical);
2657 }
2658
2659 /*******************************************************************************
2660 **
2661 **  gckOS_AllocatePagedMemoryEx
2662 **
2663 **  Allocate memory from the paged pool.
2664 **
2665 **  INPUT:
2666 **
2667 **      gckOS Os
2668 **          Pointer to an gckOS object.
2669 **
2670 **      gctBOOL Contiguous
2671 **          Need contiguous memory or not.
2672 **
2673 **      gctSIZE_T Bytes
2674 **          Number of bytes to allocate.
2675 **
2676 **  OUTPUT:
2677 **
2678 **      gctPHYS_ADDR * Physical
2679 **          Pointer to a variable that receives the physical address of the
2680 **          memory allocation.
2681 */
2682 gceSTATUS gckOS_AllocatePagedMemoryEx(
2683     IN gckOS Os,
2684     IN gctBOOL Contiguous,
2685     IN gctSIZE_T Bytes,
2686     OUT gctPHYS_ADDR * Physical
2687     )
2688 {
2689     gctINT numPages;
2690     gctINT i;
2691     PLINUX_MDL mdl;
2692     gctSTRING addr;
2693     gctSIZE_T bytes;
2694
2695     gcmkHEADER_ARG("Os=0x%0x Contiguous=%d Bytes=%lu", Os, Contiguous, Bytes);
2696
2697     /* Verify the arguments. */
2698     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2699     gcmkVERIFY_ARGUMENT(Bytes > 0);
2700     gcmkVERIFY_ARGUMENT(Physical != NULL);
2701
2702     bytes = gcmALIGN(Bytes, PAGE_SIZE);
2703
2704     numPages = GetPageCount(bytes, 0);
2705
2706     MEMORY_LOCK(Os);
2707
2708     if (Contiguous)
2709     {
2710 #if PAGE_ALLOC_LIMIT
2711         if( (g_pages_alloced + numPages) > (256*PAGE_ALLOC_LIMIT_SIZE) ) {
2712             //printk("full %d! \n", g_pages_alloced);
2713             addr = NULL;
2714         } else {
2715             addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA | __GFP_NOWARN, GetOrder(numPages));
2716             if(addr) {
2717                 g_pages_alloced += numPages;
2718                 //printk("alloc %d / %d \n", numPages, g_pages_alloced);
2719             } else {
2720                 printk("gpu : alloc %d fail! (%d/%d)\n", numPages,  g_pages_alloced, (256*PAGE_ALLOC_LIMIT_SIZE) );
2721             }
2722         }
2723 #else
2724         addr = (char *)__get_free_pages(GFP_ATOMIC | GFP_DMA | __GFP_NOWARN, GetOrder(numPages));
2725 #endif
2726     }
2727     else
2728     {
2729         addr = vmalloc(bytes);
2730     }
2731
2732     if (!addr)
2733     {
2734         gcmkTRACE_ZONE(gcvLEVEL_INFO,
2735                 gcvZONE_OS,
2736                 "gckOS_AllocatePagedMemoryEx: "
2737                 "Can't allocate memorry for size->0x%x",
2738                 (gctUINT32)bytes);
2739
2740         MEMORY_UNLOCK(Os);
2741
2742         gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
2743         return gcvSTATUS_OUT_OF_MEMORY;
2744     }
2745
2746     mdl = _CreateMdl(current->tgid);
2747
2748     if (mdl == gcvNULL)
2749     {
2750         if (Contiguous)
2751         {
2752             free_pages((unsigned int) addr, GetOrder(mdl->numPages));
2753         }
2754         else
2755         {
2756             vfree(addr);
2757         }
2758
2759         MEMORY_UNLOCK(Os);
2760
2761         gcmkHEADER_ARG("status=%d", gcvSTATUS_OUT_OF_MEMORY);
2762         return gcvSTATUS_OUT_OF_MEMORY;
2763     }
2764
2765     mdl->dmaHandle  = 0;
2766     mdl->addr       = addr;
2767     mdl->numPages   = numPages;
2768     mdl->pagedMem   = 1;
2769     mdl->contiguous = Contiguous;
2770
2771     for (i = 0; i < mdl->numPages; i++)
2772     {
2773         struct page *page;
2774
2775         if (mdl->contiguous)
2776         {
2777             page = virt_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
2778         }
2779         else
2780         {
2781             page = vmalloc_to_page((void *)(((unsigned long)addr) + i * PAGE_SIZE));
2782         }
2783
2784         SetPageReserved(page);
2785         flush_dcache_page(page);
2786     }
2787
2788     /* Return physical address. */
2789     *Physical = (gctPHYS_ADDR) mdl;
2790
2791     /*
2792      * Add this to a global list.
2793      * Will be used by get physical address
2794      * and mapuser pointer functions.
2795      */
2796     if (!Os->mdlHead)
2797     {
2798         /* Initialize the queue. */
2799         Os->mdlHead = Os->mdlTail = mdl;
2800     }
2801     else
2802     {
2803         /* Add to tail. */
2804         mdl->prev           = Os->mdlTail;
2805         Os->mdlTail->next   = mdl;
2806         Os->mdlTail         = mdl;
2807     }
2808
2809     MEMORY_UNLOCK(Os);
2810
2811     gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS,
2812                    "%s: Bytes=%lu Mdl=0x%08x Logical=0x%08x",
2813                    __FUNCTION__, bytes, mdl, mdl->addr);
2814
2815     /* Success. */
2816     gcmkHEADER_ARG("*Physical=0x%08x", *Physical);
2817     return gcvSTATUS_OK;
2818 }
2819
2820 /*******************************************************************************
2821 **
2822 **  gckOS_FreePagedMemory
2823 **
2824 **  Free memory allocated from the paged pool.
2825 **
2826 **  INPUT:
2827 **
2828 **      gckOS Os
2829 **          Pointer to an gckOS object.
2830 **
2831 **      gctPHYS_ADDR Physical
2832 **          Physical address of the allocation.
2833 **
2834 **      gctSIZE_T Bytes
2835 **          Number of bytes of the allocation.
2836 **
2837 **  OUTPUT:
2838 **
2839 **      Nothing.
2840 */
2841 gceSTATUS gckOS_FreePagedMemory(
2842     IN gckOS Os,
2843     IN gctPHYS_ADDR Physical,
2844     IN gctSIZE_T Bytes
2845     )
2846 {
2847     PLINUX_MDL  mdl = (PLINUX_MDL)Physical;
2848     gctSTRING   addr;
2849     gctINT      i;
2850
2851     /* Verify the arguments. */
2852     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2853     gcmkVERIFY_ARGUMENT(Physical != NULL);
2854
2855     gcmkTRACE_ZONE(gcvLEVEL_INFO,
2856                 gcvZONE_OS,
2857                 "in gckOS_FreePagedMemory");
2858
2859     addr = mdl->addr;
2860
2861     MEMORY_LOCK(Os);
2862
2863     for (i = 0; i < mdl->numPages; i++)
2864     {
2865         if (mdl->contiguous)
2866         {
2867             ClearPageReserved(virt_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
2868         }
2869         else
2870         {
2871             ClearPageReserved(vmalloc_to_page((gctPOINTER)(((unsigned long)addr) + i * PAGE_SIZE)));
2872         }
2873     }
2874
2875     if (mdl->contiguous)
2876     {
2877         free_pages((unsigned long)mdl->addr, GetOrder(mdl->numPages));
2878 #if PAGE_ALLOC_LIMIT
2879         g_pages_alloced -= mdl->numPages;
2880         //printk("free %d / %d \n", mdl->numPages, g_pages_alloced);
2881         if(g_pages_alloced<0)    g_pages_alloced = 0;
2882 #endif
2883     }
2884     else
2885     {
2886         vfree(mdl->addr);
2887     }
2888
2889     /* Remove the node from global list. */
2890     if (mdl == Os->mdlHead)
2891     {
2892         if ((Os->mdlHead = mdl->next) == gcvNULL)
2893         {
2894             Os->mdlTail = gcvNULL;
2895         }
2896     }
2897     else
2898     {
2899         mdl->prev->next = mdl->next;
2900
2901         if (mdl == Os->mdlTail)
2902         {
2903             Os->mdlTail = mdl->prev;
2904         }
2905         else
2906         {
2907             mdl->next->prev = mdl->prev;
2908         }
2909     }
2910
2911     MEMORY_UNLOCK(Os);
2912
2913     /* Free the structure... */
2914     gcmkVERIFY_OK(_DestroyMdl(mdl));
2915
2916     gcmkTRACE_ZONE(gcvLEVEL_INFO,
2917                 gcvZONE_OS,
2918                 "gckOS_FreePagedMemory: Bytes->0x%x, Mdl->0x%x",
2919                 (gctUINT32)Bytes,
2920                 (gctUINT32)mdl);
2921
2922     /* Success. */
2923     return gcvSTATUS_OK;
2924 }
2925
2926 /*******************************************************************************
2927 **
2928 **  gckOS_LockPages
2929 **
2930 **  Lock memory allocated from the paged pool.
2931 **
2932 **  INPUT:
2933 **
2934 **      gckOS Os
2935 **          Pointer to an gckOS object.
2936 **
2937 **      gctPHYS_ADDR Physical
2938 **          Physical address of the allocation.
2939 **
2940 **      gctSIZE_T Bytes
2941 **          Number of bytes of the allocation.
2942 **
2943 **  OUTPUT:
2944 **
2945 **      gctPOINTER * Logical
2946 **          Pointer to a variable that receives the address of the mapped
2947 **          memory.
2948 **
2949 **      gctSIZE_T * PageCount
2950 **          Pointer to a variable that receives the number of pages required for
2951 **          the page table according to the GPU page size.
2952 */
2953 gceSTATUS gckOS_LockPages(
2954     IN gckOS Os,
2955     IN gctPHYS_ADDR Physical,
2956     IN gctSIZE_T Bytes,
2957     OUT gctPOINTER * Logical,
2958     OUT gctSIZE_T * PageCount
2959     )
2960 {
2961     PLINUX_MDL      mdl;
2962     PLINUX_MDL_MAP  mdlMap;
2963     gctSTRING       addr;
2964     unsigned long   start;
2965     unsigned long   pfn;
2966     gctINT          i;
2967
2968     /* Verify the arguments. */
2969     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
2970     gcmkVERIFY_ARGUMENT(Physical != NULL);
2971     gcmkVERIFY_ARGUMENT(Logical != NULL);
2972     gcmkVERIFY_ARGUMENT(PageCount != NULL);
2973
2974     gcmkTRACE_ZONE(gcvLEVEL_INFO,
2975                 gcvZONE_OS,
2976                 "in gckOS_LockPages");
2977
2978     mdl = (PLINUX_MDL) Physical;
2979
2980     MEMORY_LOCK(Os);
2981
2982     mdlMap = FindMdlMap(mdl, current->tgid);
2983
2984     if (mdlMap == gcvNULL)
2985     {
2986         mdlMap = _CreateMdlMap(mdl, current->tgid);
2987
2988         if (mdlMap == gcvNULL)
2989         {
2990             MEMORY_UNLOCK(Os);
2991
2992             return gcvSTATUS_OUT_OF_MEMORY;
2993         }
2994     }
2995
2996     if (mdlMap->vmaAddr == gcvNULL)
2997     {
2998         down_write(&current->mm->mmap_sem);
2999
3000         mdlMap->vmaAddr = (gctSTRING)do_mmap_pgoff(NULL,
3001                         0L,
3002                         mdl->numPages * PAGE_SIZE,
3003                         PROT_READ | PROT_WRITE,
3004                         MAP_SHARED,
3005                         0);
3006
3007         up_write(&current->mm->mmap_sem);
3008
3009         gcmkTRACE_ZONE(gcvLEVEL_INFO,
3010                         gcvZONE_OS,
3011                         "gckOS_LockPages: "
3012                         "vmaAddr->0x%x for phys_addr->0x%x",
3013                         (gctUINT32)mdlMap->vmaAddr,
3014                         (gctUINT32)mdl);
3015
3016         if (mdlMap->vmaAddr == gcvNULL)
3017         {
3018             gcmkTRACE_ZONE(gcvLEVEL_INFO,
3019                         gcvZONE_OS,
3020                         "gckOS_LockPages: do_mmap_pgoff error");
3021
3022             MEMORY_UNLOCK(Os);
3023
3024             return gcvSTATUS_OUT_OF_MEMORY;
3025         }
3026
3027         mdlMap->vma = find_vma(current->mm, (unsigned long)mdlMap->vmaAddr);
3028
3029         if (mdlMap->vma == gcvNULL)
3030         {
3031             gcmkTRACE_ZONE(gcvLEVEL_INFO,
3032                         gcvZONE_OS,
3033                         "find_vma error");
3034
3035             mdlMap->vmaAddr = gcvNULL;
3036
3037             MEMORY_UNLOCK(Os);
3038
3039             return gcvSTATUS_OUT_OF_RESOURCES;
3040         }
3041
3042         mdlMap->vma->vm_flags |= VM_RESERVED;
3043         /* Make this mapping non-cached. */
3044 #if (2==gcdENABLE_MEM_CACHE)
3045         mdlMap->vma->vm_page_prot = pgprot_writecombine(mdlMap->vma->vm_page_prot);
3046 #elif (1==gcdENABLE_MEM_CACHE)
3047         // NULL
3048 #else
3049         mdlMap->vma->vm_page_prot = pgprot_noncached(mdlMap->vma->vm_page_prot);
3050 #endif
3051
3052         addr = mdl->addr;
3053
3054         /* Now map all the vmalloc pages to this user address. */
3055         down_write(&current->mm->mmap_sem);
3056
3057         if (mdl->contiguous)
3058         {
3059             /* map kernel memory to user space.. */
3060             if (remap_pfn_range(mdlMap->vma,
3061                                 mdlMap->vma->vm_start,
3062                                 virt_to_phys((gctPOINTER)mdl->addr) >> PAGE_SHIFT,
3063                                 mdlMap->vma->vm_end - mdlMap->vma->vm_start,
3064                                 mdlMap->vma->vm_page_prot) < 0)
3065             {
3066                 up_write(&current->mm->mmap_sem);
3067
3068                 gcmkTRACE_ZONE(gcvLEVEL_INFO,
3069                             gcvZONE_OS,
3070                             "gckOS_LockPages: unable to mmap ret");
3071
3072                 mdlMap->vmaAddr = gcvNULL;
3073
3074                 MEMORY_UNLOCK(Os);
3075
3076                 return gcvSTATUS_OUT_OF_MEMORY;
3077             }
3078         }
3079         else
3080         {
3081             start = mdlMap->vma->vm_start;
3082
3083             for (i = 0; i < mdl->numPages; i++)
3084             {
3085                 pfn = vmalloc_to_pfn(addr);
3086
3087                 if (remap_pfn_range(mdlMap->vma,
3088                                     start,
3089                                     pfn,
3090                                     PAGE_SIZE,
3091                                     mdlMap->vma->vm_page_prot) < 0)
3092                 {
3093                     up_write(&current->mm->mmap_sem);
3094
3095                     gcmkTRACE_ZONE(gcvLEVEL_INFO,
3096                                 gcvZONE_OS,
3097                                 "gckOS_LockPages: "
3098                                 "gctPHYS_ADDR->0x%x Logical->0x%x Unable to map addr->0x%x to start->0x%x",
3099                                 (gctUINT32)Physical,
3100                                 (gctUINT32)*Logical,
3101                                 (gctUINT32)addr,
3102                                 (gctUINT32)start);
3103
3104                     mdlMap->vmaAddr = gcvNULL;
3105
3106                     MEMORY_UNLOCK(Os);
3107
3108                     return gcvSTATUS_OUT_OF_MEMORY;
3109                 }
3110
3111                 start += PAGE_SIZE;
3112                 addr += PAGE_SIZE;
3113             }
3114         }
3115
3116         up_write(&current->mm->mmap_sem);
3117     }
3118
3119     /* Convert pointer to MDL. */
3120     *Logical = mdlMap->vmaAddr;
3121
3122     /* Return the page number according to the GPU page size. */
3123     gcmkASSERT((PAGE_SIZE % 4096) == 0);
3124     gcmkASSERT((PAGE_SIZE / 4096) >= 1);
3125
3126     *PageCount = mdl->numPages * (PAGE_SIZE / 4096);
3127
3128     MEMORY_UNLOCK(Os);
3129
3130     gcmkTRACE_ZONE(gcvLEVEL_INFO,
3131                 gcvZONE_OS,
3132                 "gckOS_LockPages: "
3133                 "gctPHYS_ADDR->0x%x Bytes->0x%x Logical->0x%x pid->%d",
3134                 (gctUINT32)Physical,
3135                 (gctUINT32)Bytes,
3136                 (gctUINT32)*Logical,
3137                 mdlMap->pid);
3138
3139     /* Success. */
3140     return gcvSTATUS_OK;
3141 }
3142
3143 /*******************************************************************************
3144 **
3145 **  gckOS_MapPages
3146 **
3147 **  Map paged memory into a page table.
3148 **
3149 **  INPUT:
3150 **
3151 **      gckOS Os
3152 **          Pointer to an gckOS object.
3153 **
3154 **      gctPHYS_ADDR Physical
3155 **          Physical address of the allocation.
3156 **
3157 **      gctSIZE_T PageCount
3158 **          Number of pages required for the physical address.
3159 **
3160 **      gctPOINTER PageTable
3161 **          Pointer to the page table to fill in.
3162 **
3163 **  OUTPUT:
3164 **
3165 **      Nothing.
3166 */
3167 gceSTATUS
3168 gckOS_MapPages(
3169     IN gckOS Os,
3170     IN gctPHYS_ADDR Physical,
3171     IN gctSIZE_T PageCount,
3172     IN gctPOINTER PageTable
3173     )
3174 {
3175     PLINUX_MDL  mdl;
3176     gctUINT32*  table;
3177     gctSTRING   addr;
3178     gctINT      i = 0;
3179
3180     /* Verify the arguments. */
3181     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3182     gcmkVERIFY_ARGUMENT(Physical != NULL);
3183     gcmkVERIFY_ARGUMENT(PageCount > 0);
3184     gcmkVERIFY_ARGUMENT(PageTable != NULL);
3185
3186     gcmkTRACE_ZONE(gcvLEVEL_INFO,
3187                 gcvZONE_OS,
3188                 "in gckOS_MapPages");
3189
3190     /* Convert pointer to MDL. */
3191     mdl = (PLINUX_MDL)Physical;
3192
3193     gcmkTRACE_ZONE(gcvLEVEL_INFO,
3194                 gcvZONE_OS,
3195                 "gckOS_MapPages: "
3196                 "Physical->0x%x PageCount->0x%x PagedMemory->?%d",
3197                 (gctUINT32)Physical,
3198                 (gctUINT32)PageCount,
3199                 mdl->pagedMem);
3200
3201     MEMORY_LOCK(Os);
3202
3203     table = (gctUINT32 *)PageTable;
3204
3205      /* Get all the physical addresses and store them in the page table. */
3206
3207     addr = mdl->addr;
3208
3209     if (mdl->pagedMem)
3210     {
3211         /* Try to get the user pages so DMA can happen. */
3212         while (PageCount-- > 0)
3213         {
3214             if (mdl->contiguous)
3215             {
3216                 *table++ = virt_to_phys(addr);
3217             }
3218             else
3219             {
3220                 *table++ = page_to_phys(vmalloc_to_page(addr));
3221             }
3222
3223             addr += 4096;
3224             i++;
3225         }
3226     }
3227     else
3228     {
3229         gcmkTRACE_ZONE(gcvLEVEL_INFO,
3230                     gcvZONE_OS,
3231                     "We should not get this call for Non Paged Memory!");
3232
3233         while (PageCount-- > 0)
3234         {
3235             *table++ = (gctUINT32)virt_to_phys(addr);
3236             addr += 4096;
3237         }
3238     }
3239
3240     MEMORY_UNLOCK(Os);
3241
3242     /* Success. */
3243     return gcvSTATUS_OK;
3244 }
3245
3246 /*******************************************************************************
3247 **
3248 **  gckOS_UnlockPages
3249 **
3250 **  Unlock memory allocated from the paged pool.
3251 **
3252 **  INPUT:
3253 **
3254 **      gckOS Os
3255 **          Pointer to an gckOS object.
3256 **
3257 **      gctPHYS_ADDR Physical
3258 **          Physical address of the allocation.
3259 **
3260 **      gctSIZE_T Bytes
3261 **          Number of bytes of the allocation.
3262 **
3263 **      gctPOINTER Logical
3264 **          Address of the mapped memory.
3265 **
3266 **  OUTPUT:
3267 **
3268 **      Nothing.
3269 */
3270 gceSTATUS gckOS_UnlockPages(
3271     IN gckOS Os,
3272     IN gctPHYS_ADDR Physical,
3273     IN gctSIZE_T Bytes,
3274     IN gctPOINTER Logical
3275     )
3276 {
3277     PLINUX_MDL_MAP          mdlMap;
3278     PLINUX_MDL              mdl = (PLINUX_MDL)Physical;
3279     struct task_struct *    task;
3280     struct mm_struct *      mm;
3281
3282     /* Verify the arguments. */
3283     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3284     gcmkVERIFY_ARGUMENT(Physical != NULL);
3285     gcmkVERIFY_ARGUMENT(Logical != NULL);
3286
3287     /* Make sure there is already a mapping...*/
3288     gcmkVERIFY_ARGUMENT(mdl->addr != NULL);
3289
3290     gcmkTRACE_ZONE(gcvLEVEL_INFO,
3291                 gcvZONE_OS,
3292                 "in gckOS_UnlockPages");
3293
3294     MEMORY_LOCK(Os);
3295
3296     mdlMap = mdl->maps;
3297
3298     while (mdlMap != gcvNULL)
3299     {
3300         if (mdlMap->vmaAddr != gcvNULL)
3301         {
3302             /* Get the current pointer for the task with stored pid. */
3303             task = FIND_TASK_BY_PID(mdlMap->pid);
3304             if(task) {
3305                 mm = get_task_mm(task);
3306                 put_task_struct(task);
3307             } else {
3308                 mm = gcvNULL;
3309             }
3310
3311             if (mm)
3312             {
3313                 down_write(&mm->mmap_sem);
3314                 do_munmap(mm, (unsigned long)Logical, mdl->numPages * PAGE_SIZE);
3315                 up_write(&mm->mmap_sem);
3316                 mmput(mm);
3317             }
3318
3319             mdlMap->vmaAddr = gcvNULL;
3320         }
3321
3322         mdlMap = mdlMap->next;
3323     }
3324
3325     MEMORY_UNLOCK(Os);
3326
3327     /* Success. */
3328     return gcvSTATUS_OK;
3329 }
3330
3331
3332 /*******************************************************************************
3333 **
3334 **  gckOS_AllocateContiguous
3335 **
3336 **  Allocate memory from the contiguous pool.
3337 **
3338 **  INPUT:
3339 **
3340 **      gckOS Os
3341 **          Pointer to an gckOS object.
3342 **
3343 **      gctBOOL InUserSpace
3344 **          gcvTRUE if the pages need to be mapped into user space.
3345 **
3346 **      gctSIZE_T * Bytes
3347 **          Pointer to the number of bytes to allocate.
3348 **
3349 **  OUTPUT:
3350 **
3351 **      gctSIZE_T * Bytes
3352 **          Pointer to a variable that receives the number of bytes allocated.
3353 **
3354 **      gctPHYS_ADDR * Physical
3355 **          Pointer to a variable that receives the physical address of the
3356 **          memory allocation.
3357 **
3358 **      gctPOINTER * Logical
3359 **          Pointer to a variable that receives the logical address of the
3360 **          memory allocation.
3361 */
3362 gceSTATUS gckOS_AllocateContiguous(
3363     IN gckOS Os,
3364     IN gctBOOL InUserSpace,
3365     IN OUT gctSIZE_T * Bytes,
3366     OUT gctPHYS_ADDR * Physical,
3367     OUT gctPOINTER * Logical
3368     )
3369 {
3370     /* Same as non-paged memory for now. */
3371     return gckOS_AllocateNonPagedMemory(Os,
3372                 InUserSpace,
3373                 Bytes,
3374                 Physical,
3375                 Logical
3376                 );
3377 }
3378
3379 /*******************************************************************************
3380 **
3381 **  gckOS_FreeContiguous
3382 **
3383 **  Free memory allocated from the contiguous pool.
3384 **
3385 **  INPUT:
3386 **
3387 **      gckOS Os
3388 **          Pointer to an gckOS object.
3389 **
3390 **      gctPHYS_ADDR Physical
3391 **          Physical address of the allocation.
3392 **
3393 **      gctPOINTER Logical
3394 **          Logicval address of the allocation.
3395 **
3396 **      gctSIZE_T Bytes
3397 **          Number of bytes of the allocation.
3398 **
3399 **  OUTPUT:
3400 **
3401 **      Nothing.
3402 */
3403 gceSTATUS gckOS_FreeContiguous(
3404     IN gckOS Os,
3405     IN gctPHYS_ADDR Physical,
3406     IN gctPOINTER Logical,
3407     IN gctSIZE_T Bytes
3408     )
3409 {
3410     /* Same of non-paged memory for now. */
3411     return gckOS_FreeNonPagedMemory(Os, Bytes, Physical, Logical);
3412 }
3413
3414 /******************************************************************************
3415 **
3416 **  gckOS_GetKernelLogical
3417 **
3418 **  Return the kernel logical pointer that corresponods to the specified
3419 **  hardware address.
3420 **
3421 **  INPUT:
3422 **
3423 **      gckOS Os
3424 **          Pointer to an gckOS object.
3425 **
3426 **      gctUINT32 Address
3427 **          Hardware physical address.
3428 **
3429 **  OUTPUT:
3430 **
3431 **      gctPOINTER * KernelPointer
3432 **          Pointer to a variable receiving the pointer in kernel address space.
3433 */
3434 gceSTATUS
3435 gckOS_GetKernelLogical(
3436     IN gckOS Os,
3437     IN gctUINT32 Address,
3438     OUT gctPOINTER * KernelPointer
3439     )
3440 {
3441     gceSTATUS status;
3442
3443     do
3444     {
3445         gckGALDEVICE device;
3446         gckKERNEL kernel;
3447         gcePOOL pool;
3448         gctUINT32 offset;
3449         gctPOINTER logical;
3450
3451         /* Extract the pointer to the gckGALDEVICE class. */
3452         device = (gckGALDEVICE) Os->device;
3453
3454         /* Kernel shortcut. */
3455         kernel = device->kernel;
3456
3457         /* Split the memory address into a pool type and offset. */
3458         gcmkERR_BREAK(gckHARDWARE_SplitMemory(
3459             kernel->hardware, Address, &pool, &offset
3460             ));
3461
3462         /* Dispatch on pool. */
3463         switch (pool)
3464         {
3465         case gcvPOOL_LOCAL_INTERNAL:
3466             /* Internal memory. */
3467             logical = device->internalLogical;
3468             break;
3469
3470         case gcvPOOL_LOCAL_EXTERNAL:
3471             /* External memory. */
3472             logical = device->externalLogical;
3473             break;
3474
3475         case gcvPOOL_SYSTEM:
3476             /* System memory. */
3477             logical = device->contiguousBase;
3478             break;
3479
3480         default:
3481             /* Invalid memory pool. */
3482             return gcvSTATUS_INVALID_ARGUMENT;
3483         }
3484
3485         /* Build logical address of specified address. */
3486         * KernelPointer = ((gctUINT8_PTR) logical) + offset;
3487
3488         /* Success. */
3489         return gcvSTATUS_OK;
3490     }
3491     while (gcvFALSE);
3492
3493     /* Return status. */
3494     return status;
3495 }
3496
3497 /*******************************************************************************
3498 **
3499 **  gckOS_MapUserPointer
3500 **
3501 **  Map a pointer from the user process into the kernel address space.
3502 **
3503 **  INPUT:
3504 **
3505 **      gckOS Os
3506 **          Pointer to an gckOS object.
3507 **
3508 **      gctPOINTER Pointer
3509 **          Pointer in user process space that needs to be mapped.
3510 **
3511 **      gctSIZE_T Size
3512 **          Number of bytes that need to be mapped.
3513 **
3514 **  OUTPUT:
3515 **
3516 **      gctPOINTER * KernelPointer
3517 **          Pointer to a variable receiving the mapped pointer in kernel address
3518 **          space.
3519 */
3520 gceSTATUS
3521 gckOS_MapUserPointer(
3522     IN gckOS Os,
3523     IN gctPOINTER Pointer,
3524     IN gctSIZE_T Size,
3525     OUT gctPOINTER * KernelPointer
3526     )
3527 {
3528 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
3529     gctPOINTER buf = gcvNULL;
3530     gctUINT32 len;
3531
3532     /* Verify the arguments. */
3533     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3534     gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
3535     gcmkVERIFY_ARGUMENT(Size > 0);
3536     gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
3537
3538     buf = kmalloc(Size, GFP_KERNEL);
3539     if (buf == gcvNULL)
3540     {
3541         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
3542             gcvZONE_OS,
3543             "Failed to allocate memory at line %d in %s.",
3544             __LINE__, __FILE__
3545             );
3546
3547         return gcvSTATUS_OUT_OF_MEMORY;
3548     }
3549
3550     len = copy_from_user(buf, Pointer, Size);
3551     if (len != 0)
3552     {
3553         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
3554             gcvZONE_OS,
3555             "Failed to copy data from user at line %d in %s.",
3556             __LINE__, __FILE__
3557             );
3558
3559         if (buf != gcvNULL)
3560         {
3561             kfree(buf);
3562         }
3563
3564         return gcvSTATUS_GENERIC_IO;
3565     }
3566
3567     *KernelPointer = buf;
3568 #else
3569     *KernelPointer = Pointer;
3570 #endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
3571
3572     return gcvSTATUS_OK;
3573 }
3574
3575 /*******************************************************************************
3576 **
3577 **  gckOS_UnmapUserPointer
3578 **
3579 **  Unmap a user process pointer from the kernel address space.
3580 **
3581 **  INPUT:
3582 **
3583 **      gckOS Os
3584 **          Pointer to an gckOS object.
3585 **
3586 **      gctPOINTER Pointer
3587 **          Pointer in user process space that needs to be unmapped.
3588 **
3589 **      gctSIZE_T Size
3590 **          Number of bytes that need to be unmapped.
3591 **
3592 **      gctPOINTER KernelPointer
3593 **          Pointer in kernel address space that needs to be unmapped.
3594 **
3595 **  OUTPUT:
3596 **
3597 **      Nothing.
3598 */
3599 gceSTATUS
3600 gckOS_UnmapUserPointer(
3601     IN gckOS Os,
3602     IN gctPOINTER Pointer,
3603     IN gctSIZE_T Size,
3604     IN gctPOINTER KernelPointer
3605     )
3606 {
3607 #if NO_USER_DIRECT_ACCESS_FROM_KERNEL
3608     gctUINT32 len;
3609
3610     /* Verify the arguments. */
3611     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3612     gcmkVERIFY_ARGUMENT(Pointer != gcvNULL);
3613     gcmkVERIFY_ARGUMENT(Size > 0);
3614     gcmkVERIFY_ARGUMENT(KernelPointer != gcvNULL);
3615
3616     len = copy_to_user(Pointer, KernelPointer, Size);
3617
3618     kfree(KernelPointer);
3619
3620     if (len != 0)
3621     {
3622         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
3623             gcvZONE_OS,
3624             "Failed to copy data to user at line %d in %s.",
3625             __LINE__, __FILE__
3626             );
3627         return gcvSTATUS_GENERIC_IO;
3628     }
3629 #endif /* NO_USER_DIRECT_ACCESS_FROM_KERNEL */
3630
3631     return gcvSTATUS_OK;
3632 }
3633
3634 /*******************************************************************************
3635 **
3636 **  gckOS_WriteMemory
3637 **
3638 **  Write data to a memory.
3639 **
3640 **  INPUT:
3641 **
3642 **      gckOS Os
3643 **          Pointer to an gckOS object.
3644 **
3645 **      gctPOINTER Address
3646 **          Address of the memory to write to.
3647 **
3648 **      gctUINT32 Data
3649 **          Data for register.
3650 **
3651 **  OUTPUT:
3652 **
3653 **      Nothing.
3654 */
3655 gceSTATUS
3656 gckOS_WriteMemory(
3657     IN gckOS Os,
3658     IN gctPOINTER Address,
3659     IN gctUINT32 Data
3660     )
3661 {
3662     /* Verify the arguments. */
3663     gcmkVERIFY_ARGUMENT(Address != NULL);
3664
3665     /* Write memory. */
3666     writel(Data, (gctUINT8 *)Address);
3667
3668     /* Success. */
3669     return gcvSTATUS_OK;
3670 }
3671
3672 /*******************************************************************************
3673 **
3674 **  gckOS_CreateSignal
3675 **
3676 **  Create a new signal.
3677 **
3678 **  INPUT:
3679 **
3680 **      gckOS Os
3681 **          Pointer to an gckOS object.
3682 **
3683 **      gctBOOL ManualReset
3684 **          If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
3685 **          order to set the signal to nonsignaled state.
3686 **          If set to gcvFALSE, the signal will automatically be set to
3687 **          nonsignaled state by gckOS_WaitSignal function.
3688 **
3689 **  OUTPUT:
3690 **
3691 **      gctSIGNAL * Signal
3692 **          Pointer to a variable receiving the created gctSIGNAL.
3693 */
3694 gceSTATUS
3695 gckOS_CreateSignal(
3696     IN gckOS Os,
3697     IN gctBOOL ManualReset,
3698     OUT gctSIGNAL * Signal
3699     )
3700 {
3701 #if USE_NEW_LINUX_SIGNAL
3702     return gcvSTATUS_NOT_SUPPORTED;
3703 #else
3704     gcsSIGNAL_PTR signal;
3705
3706     /* Verify the arguments. */
3707     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3708     gcmkVERIFY_ARGUMENT(Signal != NULL);
3709
3710     /* Create an event structure. */
3711     signal = (gcsSIGNAL_PTR)kmalloc(sizeof(gcsSIGNAL), GFP_KERNEL);
3712
3713     if (signal == gcvNULL)
3714     {
3715         return gcvSTATUS_OUT_OF_MEMORY;
3716     }
3717
3718     signal->manualReset = ManualReset;
3719
3720     init_completion(&signal->event);
3721
3722     atomic_set(&signal->ref, 1);
3723
3724     *Signal = (gctSIGNAL) signal;
3725
3726     return gcvSTATUS_OK;
3727 #endif
3728 }
3729
3730 /*******************************************************************************
3731 **
3732 **  gckOS_DestroySignal
3733 **
3734 **  Destroy a signal.
3735 **
3736 **  INPUT:
3737 **
3738 **      gckOS Os
3739 **          Pointer to an gckOS object.
3740 **
3741 **      gctSIGNAL Signal
3742 **          Pointer to the gctSIGNAL.
3743 **
3744 **  OUTPUT:
3745 **
3746 **      Nothing.
3747 */
3748 gceSTATUS
3749 gckOS_DestroySignal(
3750     IN gckOS Os,
3751     IN gctSIGNAL Signal
3752     )
3753 {
3754 #if USE_NEW_LINUX_SIGNAL
3755     return gcvSTATUS_NOT_SUPPORTED;
3756 #else
3757     gcsSIGNAL_PTR signal;
3758
3759     /* Verify the arguments. */
3760     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3761     gcmkVERIFY_ARGUMENT(Signal != NULL);
3762
3763     signal = (gcsSIGNAL_PTR) Signal;
3764
3765     if (atomic_dec_and_test(&signal->ref))
3766     {
3767          /* Free the sgianl. */
3768         kfree(Signal);
3769     }
3770
3771     /* Success. */
3772     return gcvSTATUS_OK;
3773 #endif
3774 }
3775
3776 /*******************************************************************************
3777 **
3778 **  gckOS_Signal
3779 **
3780 **  Set a state of the specified signal.
3781 **
3782 **  INPUT:
3783 **
3784 **      gckOS Os
3785 **          Pointer to an gckOS object.
3786 **
3787 **      gctSIGNAL Signal
3788 **          Pointer to the gctSIGNAL.
3789 **
3790 **      gctBOOL State
3791 **          If gcvTRUE, the signal will be set to signaled state.
3792 **          If gcvFALSE, the signal will be set to nonsignaled state.
3793 **
3794 **  OUTPUT:
3795 **
3796 **      Nothing.
3797 */
3798 gceSTATUS
3799 gckOS_Signal(
3800     IN gckOS Os,
3801     IN gctSIGNAL Signal,
3802     IN gctBOOL State
3803     )
3804 {
3805 #if USE_NEW_LINUX_SIGNAL
3806     return gcvSTATUS_NOT_SUPPORTED;
3807 #else
3808     gcsSIGNAL_PTR signal;
3809
3810     gcmkHEADER_ARG("Os=0x%x Signal=0x%x State=%d", Os, Signal, State);
3811
3812     /* Verify the arguments. */
3813     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
3814     gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
3815
3816     signal = (gcsSIGNAL_PTR) Signal;
3817
3818     /* Set the new state of the event. */
3819     if (signal->manualReset)
3820     {
3821         if (State)
3822         {
3823             /* Set the event to a signaled state. */
3824             complete_all(&signal->event);
3825         }
3826         else
3827         {
3828             /* Set the event to an unsignaled state. */
3829             INIT_COMPLETION(signal->event);
3830         }
3831     }
3832     else
3833     {
3834         if (State)
3835         {
3836             /* Set the event to a signaled state. */
3837             complete(&signal->event);
3838
3839         }
3840     }
3841
3842     /* Success. */
3843     gcmkFOOTER_NO();
3844     return gcvSTATUS_OK;
3845 #endif
3846 }
3847
3848 #if USE_NEW_LINUX_SIGNAL
3849 /*******************************************************************************
3850 **
3851 **  gckOS_UserSignal
3852 **
3853 **  Set the specified signal which is owned by a process to signaled state.
3854 **
3855 **  INPUT:
3856 **
3857 **      gckOS Os
3858 **          Pointer to an gckOS object.
3859 **
3860 **      gctSIGNAL Signal
3861 **          Pointer to the gctSIGNAL.
3862 **
3863 **      gctHANDLE Process
3864 **          Handle of process owning the signal.
3865 **
3866 **  OUTPUT:
3867 **
3868 **      Nothing.
3869 */
3870 gceSTATUS
3871 gckOS_UserSignal(
3872     IN gckOS Os,
3873     IN gctSIGNAL Signal,
3874     IN gctHANDLE Process
3875     )
3876 {
3877     gceSTATUS status;
3878     gctINT result;
3879     struct task_struct * task;
3880     struct siginfo info;
3881
3882     task = FIND_TASK_BY_PID((pid_t) Process);
3883
3884     if (task != gcvNULL)
3885     {
3886         /* Fill in the siginfo structure. */
3887         info.si_signo = Os->device->signal;
3888         info.si_errno = 0;
3889         info.si_code  = __SI_CODE(__SI_RT, SI_KERNEL);
3890         info.si_ptr   = Signal;
3891
3892         /* Send the signal. */
3893         if ((result = send_sig_info(Os->device->signal, &info, task)) < 0)
3894         {
3895             status = gcvSTATUS_GENERIC_IO;
3896
3897             gcmkTRACE(gcvLEVEL_ERROR,
3898                      "%s(%d): send_sig_info failed.",
3899                      __FUNCTION__, __LINE__);
3900         }
3901         else
3902         {
3903             /* Success. */
3904             status = gcvSTATUS_OK;
3905         }
3906         put_task_struct(task);
3907     }
3908     else
3909     {
3910         status = gcvSTATUS_GENERIC_IO;
3911
3912         gcmkTRACE(gcvLEVEL_ERROR,
3913                  "%s(%d): find_task_by_pid failed.",
3914                  __FUNCTION__, __LINE__);
3915     }
3916
3917     /* Return status. */
3918     return status;
3919 }
3920
3921 /*******************************************************************************
3922 **
3923 **  gckOS_WaitSignal
3924 **
3925 **  Wait for a signal to become signaled.
3926 **
3927 **  INPUT:
3928 **
3929 **      gckOS Os
3930 **          Pointer to an gckOS object.
3931 **
3932 **      gctSIGNAL Signal
3933 **          Pointer to the gctSIGNAL.
3934 **
3935 **      gctUINT32 Wait
3936 **          Number of milliseconds to wait.
3937 **          Pass the value of gcvINFINITE for an infinite wait.
3938 **
3939 **  OUTPUT:
3940 **
3941 **      Nothing.
3942 */
3943 gceSTATUS
3944 gckOS_WaitSignal(
3945     IN gckOS Os,
3946     IN gctSIGNAL Signal,
3947     IN gctUINT32 Wait
3948     )
3949 {
3950     return gcvSTATUS_NOT_SUPPORTED;
3951 }
3952
3953 /*******************************************************************************
3954 **
3955 **  gckOS_MapSignal
3956 **
3957 **  Map a signal in to the current process space.
3958 **
3959 **  INPUT:
3960 **
3961 **      gckOS Os
3962 **          Pointer to an gckOS object.
3963 **
3964 **      gctSIGNAL Signal
3965 **          Pointer to tha gctSIGNAL to map.
3966 **
3967 **      gctHANDLE Process
3968 **          Handle of process owning the signal.
3969 **
3970 **  OUTPUT:
3971 **
3972 **      gctSIGNAL * MappedSignal
3973 **          Pointer to a variable receiving the mapped gctSIGNAL.
3974 */
3975 gceSTATUS
3976 gckOS_MapSignal(
3977     IN gckOS Os,
3978     IN gctSIGNAL Signal,
3979     IN gctHANDLE Process,
3980     OUT gctSIGNAL * MappedSignal
3981     )
3982 {
3983     return gcvSTATUS_NOT_SUPPORTED;
3984 }
3985
3986 #else
3987
3988 /*******************************************************************************
3989 **
3990 **  gckOS_UserSignal
3991 **
3992 **  Set the specified signal which is owned by a process to signaled state.
3993 **
3994 **  INPUT:
3995 **
3996 **      gckOS Os
3997 **          Pointer to an gckOS object.
3998 **
3999 **      gctSIGNAL Signal
4000 **          Pointer to the gctSIGNAL.
4001 **
4002 **      gctHANDLE Process
4003 **          Handle of process owning the signal.
4004 **
4005 **  OUTPUT:
4006 **
4007 **      Nothing.
4008 */
4009 gceSTATUS
4010 gckOS_UserSignal(
4011     IN gckOS Os,
4012     IN gctSIGNAL Signal,
4013     IN gctHANDLE Process
4014     )
4015 {
4016     gceSTATUS status;
4017     gctSIGNAL signal;
4018
4019     gcmkHEADER_ARG("Os=0x%x Signal=%d Process=0x%x",
4020                    Os, (gctINT) Signal, Process);
4021
4022     /* Map the signal into kernel space. */
4023     gcmkONERROR(gckOS_MapSignal(Os, Signal, Process, &signal));
4024
4025     /* Signal. */
4026     status = gckOS_Signal(Os, signal, gcvTRUE);
4027     gcmkFOOTER();
4028     return status;
4029
4030 OnError:
4031     /* Return the status. */
4032     gcmkFOOTER();
4033     return status;
4034 }
4035
4036 /*******************************************************************************
4037 **
4038 **  gckOS_WaitSignal
4039 **
4040 **  Wait for a signal to become signaled.
4041 **
4042 **  INPUT:
4043 **
4044 **      gckOS Os
4045 **          Pointer to an gckOS object.
4046 **
4047 **      gctSIGNAL Signal
4048 **          Pointer to the gctSIGNAL.
4049 **
4050 **      gctUINT32 Wait
4051 **          Number of milliseconds to wait.
4052 **          Pass the value of gcvINFINITE for an infinite wait.
4053 **
4054 **  OUTPUT:
4055 **
4056 **      Nothing.
4057 */
4058 gceSTATUS
4059 gckOS_WaitSignal(
4060     IN gckOS Os,
4061     IN gctSIGNAL Signal,
4062     IN gctUINT32 Wait
4063     )
4064 {
4065     gceSTATUS status;
4066     gcsSIGNAL_PTR signal;
4067     gctUINT timeout;
4068     gctUINT rc;
4069
4070     gcmkHEADER_ARG("Os=0x%x Signal=0x%x Wait=%u", Os, Signal, Wait);
4071
4072     /* Verify the arguments. */
4073     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4074     gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
4075
4076     signal = (gcsSIGNAL_PTR) Signal;
4077
4078     /* Convert wait to milliseconds. */
4079     timeout = (Wait == gcvINFINITE) ? MAX_SCHEDULE_TIMEOUT : Wait*HZ/1000;
4080
4081     /* Linux bug ? */
4082     if (!signal->manualReset && timeout == 0) timeout = 1;
4083
4084     rc = wait_for_completion_interruptible_timeout(&signal->event, timeout);
4085     status = ((rc == 0) && !signal->event.done) ? gcvSTATUS_TIMEOUT
4086                                                 : gcvSTATUS_OK;
4087
4088     /* Return status. */
4089     gcmkFOOTER();
4090     return status;
4091 }
4092
4093 /*******************************************************************************
4094 **
4095 **  gckOS_MapSignal
4096 **
4097 **  Map a signal in to the current process space.
4098 **
4099 **  INPUT:
4100 **
4101 **      gckOS Os
4102 **          Pointer to an gckOS object.
4103 **
4104 **      gctSIGNAL Signal
4105 **          Pointer to tha gctSIGNAL to map.
4106 **
4107 **      gctHANDLE Process
4108 **          Handle of process owning the signal.
4109 **
4110 **  OUTPUT:
4111 **
4112 **      gctSIGNAL * MappedSignal
4113 **          Pointer to a variable receiving the mapped gctSIGNAL.
4114 */
4115 gceSTATUS
4116 gckOS_MapSignal(
4117     IN gckOS Os,
4118     IN gctSIGNAL Signal,
4119     IN gctHANDLE Process,
4120     OUT gctSIGNAL * MappedSignal
4121     )
4122 {
4123     gctINT signalID;
4124     gcsSIGNAL_PTR signal;
4125     gceSTATUS status;
4126     gctBOOL acquired = gcvFALSE;
4127
4128     gcmkHEADER_ARG("Os=0x%x Signal=0x%x Process=0x%x", Os, Signal, Process);
4129
4130     gcmkVERIFY_ARGUMENT(Signal != gcvNULL);
4131     gcmkVERIFY_ARGUMENT(MappedSignal != gcvNULL);
4132
4133     signalID = (gctINT) Signal - 1;
4134
4135     gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4136     acquired = gcvTRUE;
4137
4138     if (signalID >= 0 && signalID < Os->signal.tableLen)
4139     {
4140         /* It is a user space signal. */
4141         signal = Os->signal.table[signalID];
4142
4143         if (signal == gcvNULL)
4144         {
4145             gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4146         }
4147     }
4148     else
4149     {
4150         /* It is a kernel space signal structure. */
4151         signal = (gcsSIGNAL_PTR) Signal;
4152     }
4153
4154     if (atomic_inc_return(&signal->ref) <= 1)
4155     {
4156         /* The previous value is 0, it has been deleted. */
4157         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4158     }
4159
4160     /* Release the mutex. */
4161     gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
4162
4163     *MappedSignal = (gctSIGNAL) signal;
4164
4165     /* Success. */
4166     gcmkFOOTER_ARG("*MappedSignal=0x%x", *MappedSignal);
4167     return gcvSTATUS_OK;
4168
4169 OnError:
4170     if (acquired)
4171     {
4172         /* Release the mutex. */
4173         gcmkVERIFY_OK(gckOS_ReleaseMutex(Os, Os->signal.lock));
4174     }
4175
4176     /* Return the staus. */
4177     gcmkFOOTER();
4178     return status;
4179 }
4180
4181 /*******************************************************************************
4182 **
4183 **  gckOS_CreateUserSignal
4184 **
4185 **  Create a new signal to be used in the user space.
4186 **
4187 **  INPUT:
4188 **
4189 **      gckOS Os
4190 **          Pointer to an gckOS object.
4191 **
4192 **      gctBOOL ManualReset
4193 **          If set to gcvTRUE, gckOS_Signal with gcvFALSE must be called in
4194 **          order to set the signal to nonsignaled state.
4195 **          If set to gcvFALSE, the signal will automatically be set to
4196 **          nonsignaled state by gckOS_WaitSignal function.
4197 **
4198 **  OUTPUT:
4199 **
4200 **      gctINT * SignalID
4201 **          Pointer to a variable receiving the created signal's ID.
4202 */
4203 gceSTATUS
4204 gckOS_CreateUserSignal(
4205     IN gckOS Os,
4206     IN gctBOOL ManualReset,
4207     OUT gctINT * SignalID
4208     )
4209 {
4210     gcsSIGNAL_PTR signal;
4211     gctINT unused, currentID, tableLen;
4212     gctPOINTER * table;
4213     gctINT i;
4214     gceSTATUS status;
4215     gctBOOL acquired = gcvFALSE;
4216
4217     gcmkHEADER_ARG("Os=0x%0x ManualReset=%d", Os, ManualReset);
4218
4219     /* Verify the arguments. */
4220     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4221     gcmkVERIFY_ARGUMENT(SignalID != gcvNULL);
4222
4223     /* Lock the table. */
4224     gcmkONERROR(
4225         gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4226
4227     acquired = gcvTRUE;
4228
4229     if (Os->signal.unused < 1)
4230     {
4231         /* Enlarge the table. */
4232         table = (gctPOINTER *) kmalloc(
4233                     sizeof(gctPOINTER) * (Os->signal.tableLen + USER_SIGNAL_TABLE_LEN_INIT),
4234                     GFP_KERNEL);
4235
4236         if (table == gcvNULL)
4237         {
4238             /* Out of memory. */
4239             gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
4240         }
4241
4242         memset(table + Os->signal.tableLen, 0, sizeof(gctPOINTER) * USER_SIGNAL_TABLE_LEN_INIT);
4243         memcpy(table, Os->signal.table, sizeof(gctPOINTER) * Os->signal.tableLen);
4244
4245         /* Release the old table. */
4246         kfree(Os->signal.table);
4247
4248         /* Update the table. */
4249         Os->signal.table = table;
4250         Os->signal.currentID = Os->signal.tableLen;
4251         Os->signal.tableLen += USER_SIGNAL_TABLE_LEN_INIT;
4252         Os->signal.unused += USER_SIGNAL_TABLE_LEN_INIT;
4253     }
4254
4255     table = Os->signal.table;
4256     currentID = Os->signal.currentID;
4257     tableLen = Os->signal.tableLen;
4258     unused = Os->signal.unused;
4259
4260     /* Create a new signal. */
4261     gcmkONERROR(
4262         gckOS_CreateSignal(Os, ManualReset, (gctSIGNAL *) &signal));
4263
4264     /* Save the process ID. */
4265     signal->process = (gctHANDLE) current->tgid;
4266
4267     table[currentID] = signal;
4268
4269     /* Plus 1 to avoid NULL claims. */
4270     *SignalID = currentID + 1;
4271
4272     /* Update the currentID. */
4273     if (--unused > 0)
4274     {
4275         for (i = 0; i < tableLen; i++)
4276         {
4277             if (++currentID >= tableLen)
4278             {
4279                 /* Wrap to the begin. */
4280                 currentID = 0;
4281             }
4282
4283             if (table[currentID] == gcvNULL)
4284             {
4285                 break;
4286             }
4287         }
4288     }
4289
4290     Os->signal.table = table;
4291     Os->signal.currentID = currentID;
4292     Os->signal.tableLen = tableLen;
4293     Os->signal.unused = unused;
4294
4295     gcmkONERROR(
4296         gckOS_ReleaseMutex(Os, Os->signal.lock));
4297
4298     gcmkFOOTER_ARG("*SignalID=%d", gcmOPT_VALUE(SignalID));
4299     return gcvSTATUS_OK;
4300
4301 OnError:
4302     if (acquired)
4303     {
4304         /* Release the mutex. */
4305         gcmkONERROR(
4306             gckOS_ReleaseMutex(Os, Os->signal.lock));
4307     }
4308
4309     /* Return the staus. */
4310     gcmkFOOTER();
4311     return status;
4312 }
4313
4314 /*******************************************************************************
4315 **
4316 **  gckOS_DestroyUserSignal
4317 **
4318 **  Destroy a signal to be used in the user space.
4319 **
4320 **  INPUT:
4321 **
4322 **      gckOS Os
4323 **          Pointer to an gckOS object.
4324 **
4325 **      gctINT SignalID
4326 **          The signal's ID.
4327 **
4328 **  OUTPUT:
4329 **
4330 **      Nothing.
4331 */
4332 gceSTATUS
4333 gckOS_DestroyUserSignal(
4334     IN gckOS Os,
4335     IN gctINT SignalID
4336     )
4337 {
4338     gceSTATUS status;
4339     gcsSIGNAL_PTR signal;
4340     gctBOOL acquired = gcvFALSE;
4341
4342     gcmkHEADER_ARG("Os=0x%x SignalID=%d", Os, SignalID);
4343
4344     /* Verify the arguments. */
4345     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4346
4347     gcmkONERROR(
4348         gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4349
4350     acquired = gcvTRUE;
4351
4352     if (SignalID < 1 || SignalID > Os->signal.tableLen)
4353     {
4354         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4355             gcvZONE_OS,
4356             "gckOS_DestroyUserSignal: invalid signal->%d.",
4357             (gctINT) SignalID
4358             );
4359
4360         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4361     }
4362
4363     SignalID -= 1;
4364
4365     signal = Os->signal.table[SignalID];
4366
4367     if (signal == gcvNULL)
4368     {
4369         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4370             gcvZONE_OS,
4371             "gckOS_DestroyUserSignal: signal is NULL."
4372             );
4373
4374         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4375     }
4376
4377     /* Check to see if the process is the owner of the signal. */
4378     if (signal->process != (gctHANDLE) current->tgid)
4379     {
4380         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4381             gcvZONE_OS,
4382             "gckOS_DestroyUserSignal: process id doesn't match. ",
4383             "signal->process: %d, current->tgid: %d",
4384             signal->process,
4385             current->tgid);
4386
4387         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4388     }
4389
4390     gcmkONERROR(
4391         gckOS_DestroySignal(Os, signal));
4392
4393     /* Update the table. */
4394     Os->signal.table[SignalID] = gcvNULL;
4395     if (Os->signal.unused++ == 0)
4396     {
4397         Os->signal.currentID = SignalID;
4398     }
4399
4400     gcmkVERIFY_OK(
4401         gckOS_ReleaseMutex(Os, Os->signal.lock));
4402
4403     /* Success. */
4404     gcmkFOOTER_NO();
4405     return gcvSTATUS_OK;
4406
4407 OnError:
4408     if (acquired)
4409     {
4410         /* Release the mutex. */
4411         gcmkONERROR(
4412             gckOS_ReleaseMutex(Os, Os->signal.lock));
4413     }
4414
4415     /* Return the status. */
4416     gcmkFOOTER();
4417     return status;
4418 }
4419
4420 /*******************************************************************************
4421 **
4422 **  gckOS_WaitUserSignal
4423 **
4424 **  Wait for a signal used in the user mode to become signaled.
4425 **
4426 **  INPUT:
4427 **
4428 **      gckOS Os
4429 **          Pointer to an gckOS object.
4430 **
4431 **      gctINT SignalID
4432 **          Signal ID.
4433 **
4434 **      gctUINT32 Wait
4435 **          Number of milliseconds to wait.
4436 **          Pass the value of gcvINFINITE for an infinite wait.
4437 **
4438 **  OUTPUT:
4439 **
4440 **      Nothing.
4441 */
4442 gceSTATUS
4443 gckOS_WaitUserSignal(
4444     IN gckOS Os,
4445     IN gctINT SignalID,
4446     IN gctUINT32 Wait
4447     )
4448 {
4449     gceSTATUS status;
4450     gcsSIGNAL_PTR signal;
4451     gctBOOL acquired = gcvFALSE;
4452
4453     gcmkHEADER_ARG("Os=0x%x SignalID=%d Wait=%u", Os, SignalID, Wait);
4454
4455     /* Verify the arguments. */
4456     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4457
4458     gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4459     acquired = gcvTRUE;
4460
4461     if (SignalID < 1 || SignalID > Os->signal.tableLen)
4462     {
4463         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4464             gcvZONE_OS,
4465             "gckOS_WaitSignal: invalid signal.",
4466             SignalID
4467             );
4468
4469         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4470     }
4471
4472     SignalID -= 1;
4473
4474     signal = Os->signal.table[SignalID];
4475
4476     gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
4477     acquired = gcvFALSE;
4478
4479     if (signal == gcvNULL)
4480     {
4481         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4482             gcvZONE_OS,
4483             "gckOS_WaitSignal: signal is NULL."
4484             );
4485
4486         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4487     }
4488
4489     if (signal->process != (gctHANDLE) current->tgid)
4490     {
4491         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4492             gcvZONE_OS,
4493             "gckOS_WaitUserSignal: process id doesn't match. "
4494             "signal->process: %d, current->tgid: %d",
4495             signal->process,
4496             current->tgid);
4497
4498         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4499     }
4500
4501
4502 do{
4503     status = gckOS_WaitSignal(Os, signal, Wait==gcvINFINITE?5000:Wait);
4504 if(Wait==gcvINFINITE&&status==gcvSTATUS_TIMEOUT){gcmkPRINT("$$FLUSH$$");}
4505 }while(status==gcvSTATUS_TIMEOUT&&Wait==gcvINFINITE);
4506
4507     /* Return the status. */
4508     gcmkFOOTER();
4509     return status;
4510
4511 OnError:
4512     if (acquired)
4513     {
4514         /* Release the mutex. */
4515         gcmkONERROR(
4516             gckOS_ReleaseMutex(Os, Os->signal.lock));
4517     }
4518
4519     /* Return the staus. */
4520     gcmkFOOTER();
4521     return status;
4522 }
4523
4524 /*******************************************************************************
4525 **
4526 **  gckOS_SignalUserSignal
4527 **
4528 **  Set a state of the specified signal to be used in the user space.
4529 **
4530 **  INPUT:
4531 **
4532 **      gckOS Os
4533 **          Pointer to an gckOS object.
4534 **
4535 **      gctINT SignalID
4536 **          SignalID.
4537 **
4538 **      gctBOOL State
4539 **          If gcvTRUE, the signal will be set to signaled state.
4540 **          If gcvFALSE, the signal will be set to nonsignaled state.
4541 **
4542 **  OUTPUT:
4543 **
4544 **      Nothing.
4545 */
4546 gceSTATUS
4547 gckOS_SignalUserSignal(
4548     IN gckOS Os,
4549     IN gctINT SignalID,
4550     IN gctBOOL State
4551     )
4552 {
4553     gceSTATUS status;
4554     gcsSIGNAL_PTR signal;
4555     gctBOOL acquired = gcvFALSE;
4556
4557     gcmkHEADER_ARG("Os=0x%x SignalID=%d State=%d", Os, SignalID, State);
4558
4559     /* Verify the arguments. */
4560     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4561
4562     gcmkONERROR(gckOS_AcquireMutex(Os, Os->signal.lock, gcvINFINITE));
4563     acquired = gcvTRUE;
4564
4565     if ((SignalID < 1)
4566     ||  (SignalID > Os->signal.tableLen)
4567     )
4568     {
4569         gcmkTRACE_ZONE(gcvLEVEL_ERROR,  gcvZONE_OS,
4570                        "gckOS_WaitSignal: invalid signal->%d.", SignalID);
4571
4572         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4573     }
4574
4575     SignalID -= 1;
4576
4577     signal = Os->signal.table[SignalID];
4578
4579     gcmkONERROR(gckOS_ReleaseMutex(Os, Os->signal.lock));
4580     acquired = gcvFALSE;
4581
4582     if (signal == gcvNULL)
4583     {
4584         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4585             gcvZONE_OS,
4586             "gckOS_WaitSignal: signal is NULL."
4587             );
4588
4589         gcmkONERROR(gcvSTATUS_INVALID_REQUEST);
4590     }
4591
4592     if (signal->process != (gctHANDLE) current->tgid)
4593     {
4594         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4595             gcvZONE_OS,
4596             "gckOS_DestroyUserSignal: process id doesn't match. ",
4597             "signal->process: %d, current->tgid: %d",
4598             signal->process,
4599             current->tgid);
4600
4601         gcmkONERROR(gcvSTATUS_INVALID_ARGUMENT);
4602     }
4603
4604     status = gckOS_Signal(Os, signal, State);
4605
4606     /* Success. */
4607     gcmkFOOTER();
4608     return status;
4609
4610 OnError:
4611     if (acquired)
4612     {
4613         /* Release the mutex. */
4614         gcmkONERROR(
4615             gckOS_ReleaseMutex(Os, Os->signal.lock));
4616     }
4617
4618     /* Return the staus. */
4619     gcmkFOOTER();
4620     return status;
4621 }
4622
4623 gceSTATUS
4624 gckOS_DestroyAllUserSignals(
4625     IN gckOS Os
4626     )
4627 {
4628     gctINT signal;
4629
4630     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4631
4632     gcmkVERIFY_OK(gckOS_AcquireMutex(Os,
4633         Os->signal.lock,
4634         gcvINFINITE
4635         ));
4636
4637     if (Os->signal.unused == Os->signal.tableLen)
4638     {
4639         gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
4640             Os->signal.lock
4641             ));
4642
4643         return gcvSTATUS_OK;
4644     }
4645
4646     for (signal = 0; signal < Os->signal.tableLen; signal++)
4647     {
4648         if (Os->signal.table[signal] != gcvNULL &&
4649             ((gcsSIGNAL_PTR)Os->signal.table[signal])->process == (gctHANDLE) current->tgid)
4650         {
4651             gckOS_DestroySignal(Os, Os->signal.table[signal]);
4652
4653             /* Update the signal table. */
4654             Os->signal.table[signal] = gcvNULL;
4655             if (Os->signal.unused++ == 0)
4656             {
4657                 Os->signal.currentID = signal;
4658             }
4659         }
4660     }
4661
4662     gcmkVERIFY_OK(gckOS_ReleaseMutex(Os,
4663         Os->signal.lock
4664         ));
4665
4666     return gcvSTATUS_OK;
4667 }
4668
4669 #endif /* USE_NEW_LINUX_SIGNAL */
4670
4671 /*******************************************************************************
4672 **
4673 **  gckOS_MapUserMemory
4674 **
4675 **  Lock down a user buffer and return an DMA'able address to be used by the
4676 **  hardware to access it.
4677 **
4678 **  INPUT:
4679 **
4680 **      gctPOINTER Memory
4681 **          Pointer to memory to lock down.
4682 **
4683 **      gctSIZE_T Size
4684 **          Size in bytes of the memory to lock down.
4685 **
4686 **  OUTPUT:
4687 **
4688 **      gctPOINTER * Info
4689 **          Pointer to variable receiving the information record required by
4690 **          gckOS_UnmapUserMemory.
4691 **
4692 **      gctUINT32_PTR Address
4693 **          Pointer to a variable that will receive the address DMA'able by the
4694 **          hardware.
4695 */
4696 gceSTATUS
4697 gckOS_MapUserMemory(
4698     IN gckOS Os,
4699     IN gctPOINTER Memory,
4700     IN gctSIZE_T Size,
4701     OUT gctPOINTER * Info,
4702     OUT gctUINT32_PTR Address
4703     )
4704 {
4705     gceSTATUS status;
4706     gctSIZE_T pageCount, i, j;
4707     gctUINT32_PTR pageTable;
4708     gctUINT32 address;
4709     gctUINT32 start, end, memory;
4710     gctINT result = 0;
4711
4712     gcsPageInfo_PTR info = gcvNULL;
4713     struct page **pages = gcvNULL;
4714
4715     /* Verify the arguments. */
4716     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
4717     gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
4718     gcmkVERIFY_ARGUMENT(Size > 0);
4719     gcmkVERIFY_ARGUMENT(Info != gcvNULL);
4720     gcmkVERIFY_ARGUMENT(Address != gcvNULL);
4721
4722     gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
4723         gcvZONE_OS,
4724         "[gckOS_MapUserMemory] enter."
4725         );
4726
4727     do
4728     {
4729         memory = (gctUINT32) Memory;
4730
4731         /* Get the number of required pages. */
4732         end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
4733         start = memory >> PAGE_SHIFT;
4734         pageCount = end - start;
4735
4736         gcmkTRACE_ZONE(gcvLEVEL_INFO,
4737             gcvZONE_OS,
4738             "[gckOS_MapUserMemory] pageCount: %d.",
4739             pageCount
4740             );
4741
4742         /* Invalid argument. */
4743         if (pageCount == 0)
4744         {
4745             return gcvSTATUS_INVALID_ARGUMENT;
4746         }
4747
4748         /* Overflow. */
4749         if ((memory + Size) < memory)
4750         {
4751             return gcvSTATUS_INVALID_ARGUMENT;
4752         }
4753
4754         MEMORY_MAP_LOCK(Os);
4755
4756         /* Allocate the Info struct. */
4757         info = (gcsPageInfo_PTR)kmalloc(sizeof(gcsPageInfo), GFP_KERNEL);
4758
4759         if (info == gcvNULL)
4760         {
4761             status = gcvSTATUS_OUT_OF_MEMORY;
4762             break;
4763         }
4764
4765         /* Allocate the array of page addresses. */
4766         pages = (struct page **)kmalloc(pageCount * sizeof(struct page *), GFP_KERNEL);
4767
4768         if (pages == gcvNULL)
4769         {
4770             status = gcvSTATUS_OUT_OF_MEMORY;
4771             break;
4772         }
4773
4774         /* Get the user pages. */
4775         down_read(&current->mm->mmap_sem);
4776         result = get_user_pages(current,
4777                     current->mm,
4778                     memory & PAGE_MASK,
4779                     pageCount,
4780                     1,
4781                     0,
4782                     pages,
4783                     NULL
4784                     );
4785         up_read(&current->mm->mmap_sem);
4786
4787         if (result <=0 || result < pageCount)
4788         {
4789             struct vm_area_struct *vma;
4790
4791             vma = find_vma(current->mm, memory);
4792
4793             if (vma && (vma->vm_flags & VM_PFNMAP) )
4794             {
4795                 do
4796                 {
4797                     pte_t       * pte;
4798                     spinlock_t  * ptl;
4799                     unsigned long pfn;
4800
4801                     pgd_t * pgd = pgd_offset(current->mm, memory);
4802                     pud_t * pud = pud_alloc(current->mm, pgd, memory);
4803                     if (pud)
4804                     {
4805                         pmd_t * pmd = pmd_alloc(current->mm, pud, memory);
4806                         if (pmd)
4807                         {
4808                             pte = pte_offset_map_lock(current->mm, pmd, memory, &ptl);
4809                             if (!pte)
4810                             {
4811                                 break;
4812                             }
4813                         }
4814                         else
4815                         {
4816                             break;
4817                         }
4818                     }
4819                     else
4820                     {
4821                         break;
4822                     }
4823
4824                     pfn      = pte_pfn(*pte);
4825                     *Address = ((pfn << PAGE_SHIFT) | (((unsigned long)Memory) & ~PAGE_MASK))
4826                                 - Os->baseAddress;
4827                     *Info    = gcvNULL;
4828
4829                     pte_unmap_unlock(pte, ptl);
4830
4831                     /* Release page info struct. */
4832                     if (info != gcvNULL)
4833                     {
4834                         /* Free the page info struct. */
4835                         kfree(info);
4836                     }
4837
4838                     if (pages != gcvNULL)
4839                     {
4840                         /* Free the page table. */
4841                         kfree(pages);
4842                     }
4843
4844                     MEMORY_MAP_UNLOCK(Os);
4845
4846                     return gcvSTATUS_OK;
4847                 }
4848                 while (gcvFALSE);
4849
4850                 *Address = ~0;
4851                 *Info = gcvNULL;
4852
4853                 status = gcvSTATUS_OUT_OF_RESOURCES;
4854                 break;
4855             }
4856             else
4857             {
4858                 status = gcvSTATUS_OUT_OF_RESOURCES;
4859                 break;
4860             }
4861         }
4862
4863         for (i = 0; i < pageCount; i++)
4864         {
4865             /* Flush the data cache. */
4866 #ifdef ANDROID
4867             dma_sync_single_for_device(
4868                         gcvNULL,
4869                         page_to_phys(pages[i]),
4870                         PAGE_SIZE,
4871                         DMA_TO_DEVICE);
4872 #else
4873             flush_dcache_page(pages[i]);
4874 #endif
4875         }
4876
4877         /* Allocate pages inside the page table. */
4878         gcmkERR_BREAK(gckMMU_AllocatePages(Os->device->kernel->mmu,
4879                                           pageCount * (PAGE_SIZE/4096),
4880                                           (gctPOINTER *) &pageTable,
4881                                           &address));
4882
4883         /* Fill the page table. */
4884         for (i = 0; i < pageCount; i++)
4885         {
4886             /* Get the physical address from page struct. */
4887             pageTable[i * (PAGE_SIZE/4096)] = page_to_phys(pages[i]);
4888
4889             for (j = 1; j < (PAGE_SIZE/4096); j++)
4890             {
4891                 pageTable[i * (PAGE_SIZE/4096) + j] = pageTable[i * (PAGE_SIZE/4096)] + 4096 * j;
4892             }
4893
4894             gcmkTRACE_ZONE(gcvLEVEL_INFO,
4895                 gcvZONE_OS,
4896                 "[gckOS_MapUserMemory] pages[%d]: 0x%x, pageTable[%d]: 0x%x.",
4897                 i, pages[i],
4898                 i, pageTable[i]);
4899         }
4900
4901         /* Save pointer to page table. */
4902         info->pageTable = pageTable;
4903         info->pages = pages;
4904
4905         *Info = (gctPOINTER) info;
4906
4907         gcmkTRACE_ZONE(gcvLEVEL_INFO,
4908             gcvZONE_OS,
4909             "[gckOS_MapUserMemory] info->pages: 0x%x, info->pageTable: 0x%x, info: 0x%x.",
4910             info->pages,
4911             info->pageTable,
4912             info
4913             );
4914
4915         /* Return address. */
4916         *Address = address + (memory & ~PAGE_MASK);
4917
4918         gcmkTRACE_ZONE(gcvLEVEL_INFO,
4919             gcvZONE_OS,
4920             "[gckOS_MapUserMemory] Address: 0x%x.",
4921             *Address
4922             );
4923
4924         /* Success. */
4925         status = gcvSTATUS_OK;
4926     }
4927     while (gcvFALSE);
4928
4929     if (gcmIS_ERROR(status))
4930     {
4931         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4932             gcvZONE_OS,
4933             "[gckOS_MapUserMemory] error occured: %d.",
4934             status
4935             );
4936
4937         /* Release page array. */
4938         if (result > 0 && pages != gcvNULL)
4939         {
4940             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4941                 gcvZONE_OS,
4942                 "[gckOS_MapUserMemory] error: page table is freed."
4943                 );
4944
4945             for (i = 0; i < result; i++)
4946             {
4947                 if (pages[i] == gcvNULL)
4948                 {
4949                     break;
4950                 }
4951 #ifdef ANDROID
4952                 dma_sync_single_for_device(
4953                             gcvNULL,
4954                             page_to_phys(pages[i]),
4955                             PAGE_SIZE,
4956                             DMA_FROM_DEVICE);
4957 #endif
4958                 page_cache_release(pages[i]);
4959             }
4960         }
4961
4962         if (pages != gcvNULL)
4963         {
4964             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4965                 gcvZONE_OS,
4966                 "[gckOS_MapUserMemory] error: pages is freed."
4967                 );
4968
4969             /* Free the page table. */
4970             kfree(pages);
4971             info->pages = gcvNULL;
4972         }
4973
4974         /* Release page info struct. */
4975         if (info != gcvNULL)
4976         {
4977             gcmkTRACE_ZONE(gcvLEVEL_ERROR,
4978                 gcvZONE_OS,
4979                 "[gckOS_MapUserMemory] error: info is freed."
4980                 );
4981
4982             /* Free the page info struct. */
4983             kfree(info);
4984             *Info = gcvNULL;
4985         }
4986     }
4987
4988     MEMORY_MAP_UNLOCK(Os);
4989
4990     gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
4991         gcvZONE_OS,
4992         "[gckOS_MapUserMemory] leave."
4993         );
4994
4995     /* Return the status. */
4996     return status;
4997 }
4998
4999 /*******************************************************************************
5000 **
5001 **  gckOS_UnmapUserMemory
5002 **
5003 **  Unlock a user buffer and that was previously locked down by
5004 **  gckOS_MapUserMemory.
5005 **
5006 **  INPUT:
5007 **
5008 **      gctPOINTER Memory
5009 **          Pointer to memory to unlock.
5010 **
5011 **      gctSIZE_T Size
5012 **          Size in bytes of the memory to unlock.
5013 **
5014 **      gctPOINTER Info
5015 **          Information record returned by gckOS_MapUserMemory.
5016 **
5017 **      gctUINT32_PTR Address
5018 **          The address returned by gckOS_MapUserMemory.
5019 **
5020 **  OUTPUT:
5021 **
5022 **      Nothing.
5023 */
5024 gceSTATUS
5025 gckOS_UnmapUserMemory(
5026     IN gckOS Os,
5027     IN gctPOINTER Memory,
5028     IN gctSIZE_T Size,
5029     IN gctPOINTER Info,
5030     IN gctUINT32 Address
5031     )
5032 {
5033     gceSTATUS status;
5034     gctUINT32 memory, start, end;
5035     gcsPageInfo_PTR info;
5036     gctSIZE_T pageCount, i;
5037     struct page **pages;
5038
5039     /* Verify the arguments. */
5040     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5041     gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5042     gcmkVERIFY_ARGUMENT(Size > 0);
5043     gcmkVERIFY_ARGUMENT(Info != gcvNULL);
5044
5045     gcmkTRACE_ZONE(gcvLEVEL_VERBOSE,
5046         gcvZONE_OS,
5047         "[gckOS_UnmapUserMemory] enter."
5048         );
5049
5050     do
5051     {
5052         info = (gcsPageInfo_PTR) Info;
5053
5054         if (info == gcvNULL)
5055         {
5056             return gcvSTATUS_OK;
5057         }
5058
5059         pages = info->pages;
5060
5061         gcmkTRACE_ZONE(gcvLEVEL_INFO,
5062             gcvZONE_OS,
5063             "[gckOS_UnmapUserMemory] info: 0x%x, pages: 0x%x.",
5064             info,
5065             pages
5066             );
5067
5068         /* Invalid page array. */
5069         if (pages == gcvNULL)
5070         {
5071             return gcvSTATUS_INVALID_ARGUMENT;
5072         }
5073
5074         memory = (gctUINT32) Memory;
5075         end = (memory + Size + PAGE_SIZE - 1) >> PAGE_SHIFT;
5076         start = memory >> PAGE_SHIFT;
5077         pageCount = end - start;
5078
5079         /* Overflow. */
5080         if ((memory + Size) < memory)
5081         {
5082             return gcvSTATUS_INVALID_ARGUMENT;
5083         }
5084
5085         /* Invalid argument. */
5086         if (pageCount == 0)
5087         {
5088             return gcvSTATUS_INVALID_ARGUMENT;
5089         }
5090
5091         gcmkTRACE_ZONE(gcvLEVEL_INFO,
5092             gcvZONE_OS,
5093             "[gckOS_UnmapUserMemory] memory: 0x%x, pageCount: %d, pageTable: 0x%x.",
5094             memory,
5095             pageCount,
5096             info->pageTable
5097             );
5098
5099         MEMORY_MAP_LOCK(Os);
5100
5101         /* Free the pages from the MMU. */
5102         gcmkERR_BREAK(gckMMU_FreePages(Os->device->kernel->mmu,
5103                                       info->pageTable,
5104                                       pageCount * (PAGE_SIZE/4096)
5105                                       ));
5106
5107         /* Release the page cache. */
5108         for (i = 0; i < pageCount; i++)
5109         {
5110             gcmkTRACE_ZONE(gcvLEVEL_INFO,
5111                 gcvZONE_OS,
5112                 "[gckOS_UnmapUserMemory] pages[%d]: 0x%x.",
5113                 i,
5114                 pages[i]
5115                 );
5116
5117             if (!PageReserved(pages[i]))
5118             {
5119                 SetPageDirty(pages[i]);
5120             }
5121
5122 #ifdef ANDROID
5123             dma_sync_single_for_device(
5124                         gcvNULL,
5125                         page_to_phys(pages[i]),
5126                         PAGE_SIZE,
5127                         DMA_FROM_DEVICE);
5128 #endif
5129             page_cache_release(pages[i]);
5130         }
5131
5132         /* Success. */
5133         status = gcvSTATUS_OK;
5134     }
5135     while (gcvFALSE);
5136
5137     if (info != gcvNULL)
5138     {
5139         /* Free the page array. */
5140         if (info->pages != gcvNULL)
5141         {
5142             kfree(info->pages);
5143         }
5144
5145         kfree(info);
5146     }
5147
5148     MEMORY_MAP_UNLOCK(Os);
5149
5150     /* Return the status. */
5151     return status;
5152 }
5153
5154 /*******************************************************************************
5155 **
5156 **  gckOS_GetBaseAddress
5157 **
5158 **  Get the base address for the physical memory.
5159 **
5160 **  INPUT:
5161 **
5162 **      gckOS Os
5163 **          Pointer to the gckOS object.
5164 **
5165 **  OUTPUT:
5166 **
5167 **      gctUINT32_PTR BaseAddress
5168 **          Pointer to a variable that will receive the base address.
5169 */
5170 gceSTATUS
5171 gckOS_GetBaseAddress(
5172     IN gckOS Os,
5173     OUT gctUINT32_PTR BaseAddress
5174     )
5175 {
5176     /* Verify the arguments. */
5177     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5178     gcmkVERIFY_ARGUMENT(BaseAddress != gcvNULL);
5179
5180     /* Return base address. */
5181     *BaseAddress = Os->baseAddress;
5182
5183     /* Success. */
5184     return gcvSTATUS_OK;
5185 }
5186
5187 gceSTATUS
5188 gckOS_SuspendInterrupt(
5189     IN gckOS Os
5190     )
5191 {
5192     /* Verify the arguments. */
5193     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5194
5195     disable_irq(Os->device->irqLine);
5196
5197     return gcvSTATUS_OK;
5198 }
5199
5200 gceSTATUS
5201 gckOS_ResumeInterrupt(
5202     IN gckOS Os
5203     )
5204 {
5205     /* Verify the arguments. */
5206     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5207
5208     enable_irq(Os->device->irqLine);
5209
5210     return gcvSTATUS_OK;
5211 }
5212
5213 gceSTATUS
5214 gckOS_MemCopy(
5215         IN gctPOINTER Destination,
5216         IN gctCONST_POINTER Source,
5217         IN gctSIZE_T Bytes
5218         )
5219 {
5220         gcmkVERIFY_ARGUMENT(Destination != NULL);
5221         gcmkVERIFY_ARGUMENT(Source != NULL);
5222         gcmkVERIFY_ARGUMENT(Bytes > 0);
5223
5224         memcpy(Destination, Source, Bytes);
5225
5226         return gcvSTATUS_OK;
5227 }
5228
5229 gceSTATUS
5230 gckOS_ZeroMemory(
5231     IN gctPOINTER Memory,
5232     IN gctSIZE_T Bytes
5233     )
5234 {
5235     gcmkHEADER_ARG("Memory=0x%x Bytes=%lu", Memory, Bytes);
5236
5237     gcmkVERIFY_ARGUMENT(Memory != gcvNULL);
5238     gcmkVERIFY_ARGUMENT(Bytes > 0);
5239
5240     memset(Memory, 0, Bytes);
5241
5242     gcmkFOOTER_NO();
5243     return gcvSTATUS_OK;
5244 }
5245
5246 #if gcdkUSE_MEMORY_RECORD
5247 MEMORY_RECORD_PTR
5248 CreateMemoryRecord(
5249     gckOS Os,
5250     MEMORY_RECORD_PTR List,
5251     gcuVIDMEM_NODE_PTR Node,
5252     gceSURF_TYPE Type,
5253     gctSIZE_T Bytes
5254     )
5255 {
5256     MEMORY_RECORD_PTR   mr;
5257
5258     mr = (MEMORY_RECORD_PTR)kmalloc(sizeof(struct MEMORY_RECORD), GFP_ATOMIC);
5259     if (mr == gcvNULL) return gcvNULL;
5260
5261     MEMORY_LOCK(Os);
5262
5263     mr->node            = Node;
5264     mr->type            = Type;
5265     mr->bytes           = Bytes;
5266
5267 #if gcdkREPORT_VIDMEM_USAGE
5268     AllocatedSurfaceTotal[Type] += Bytes;
5269     AllocatedSurfaceMax[Type] = (AllocatedSurfaceMax[Type] > AllocatedSurfaceTotal[Type])
5270                        ? AllocatedSurfaceMax[Type] : AllocatedSurfaceTotal[Type];
5271     AllocatedSurfaceMax[12] += Bytes;
5272     if(AllocatedSurfaceMax[12] > AllocatedSurfaceMax[13])
5273     {
5274         AllocatedSurfaceMax[13] = AllocatedSurfaceMax[12];
5275     }
5276 #endif
5277
5278     mr->prev            = List->prev;
5279     mr->next            = List;
5280     List->prev->next    = mr;
5281     List->prev          = mr;
5282
5283     MEMORY_UNLOCK(Os);
5284
5285     return mr;
5286 }
5287
5288 void
5289 DestoryMemoryRecord(
5290     gckOS Os,
5291     MEMORY_RECORD_PTR Mr
5292     )
5293 {
5294     MEMORY_LOCK(Os);
5295
5296 #if gcdkREPORT_VIDMEM_USAGE
5297     AllocatedSurfaceTotal[Mr->type] -= Mr->bytes;
5298     AllocatedSurfaceMax[12] -= Mr->bytes;
5299 #endif
5300
5301     Mr->prev->next      = Mr->next;
5302     Mr->next->prev      = Mr->prev;
5303
5304     MEMORY_UNLOCK(Os);
5305
5306     kfree(Mr);
5307 }
5308
5309 MEMORY_RECORD_PTR
5310 FindMemoryRecord(
5311     gckOS Os,
5312     MEMORY_RECORD_PTR List,
5313     gcuVIDMEM_NODE_PTR Node
5314     )
5315 {
5316     MEMORY_RECORD_PTR mr;
5317
5318     MEMORY_LOCK(Os);
5319
5320     mr = List->next;
5321
5322     while (mr != List)
5323     {
5324         if (mr->node == Node)
5325         {
5326             MEMORY_UNLOCK(Os);
5327
5328             return mr;
5329         }
5330
5331         mr = mr->next;
5332     }
5333
5334     MEMORY_UNLOCK(Os);
5335
5336     return gcvNULL;
5337 }
5338
5339 void
5340 FreeAllMemoryRecord(
5341     gckOS Os,
5342     MEMORY_RECORD_PTR List
5343     )
5344 {
5345     MEMORY_RECORD_PTR mr;
5346     gctUINT i = 0;
5347
5348     MEMORY_LOCK(Os);
5349
5350 #if gcdkREPORT_VIDMEM_USAGE
5351     for (; i < 12; i++) {
5352         printk("AllocatedSurfaceTotal[%s]:\t %12lluK, AllocatedSurfaceMax[%s]:\t %12lluK\n",
5353                 pszSurfaceType[i], AllocatedSurfaceTotal[i]/1024,
5354                 pszSurfaceType[i], AllocatedSurfaceMax[i]/1024);
5355
5356         AllocatedSurfaceTotal[i] = 0;
5357         AllocatedSurfaceMax[i] = 0;
5358     }
5359     printk("AllocatedSurfaceMax[unfreed]:\t %12lluK\n", AllocatedSurfaceMax[12]/1024);
5360     printk("AllocatedSurfaceMax[total]:\t %12lluK\n", AllocatedSurfaceMax[13]/1024);
5361     AllocatedSurfaceMax[12] = AllocatedSurfaceMax[13] = 0;
5362     i = 0;
5363 #endif
5364
5365     while (List->next != List)
5366     {
5367         mr = List->next;
5368
5369         mr->prev->next      = mr->next;
5370         mr->next->prev      = mr->prev;
5371
5372         i++;
5373
5374         MEMORY_UNLOCK(Os);
5375
5376         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
5377                 gcvZONE_OS,
5378                 "Unfreed %s memory: node: %p",
5379                 (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)?
5380                     "video" : (mr->node->Virtual.contiguous)?
5381                         "contiguous" : "virtual",
5382                 mr->node);
5383
5384         while (gcvTRUE)
5385         {
5386             if (mr->node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
5387             {
5388                 if (mr->node->VidMem.locked == 0) break;
5389             }
5390             else
5391             {
5392                 if (mr->node->Virtual.locked == 0) break;
5393             }
5394
5395             gckVIDMEM_Unlock(mr->node, gcvSURF_TYPE_UNKNOWN, gcvNULL);
5396         }
5397
5398         gckVIDMEM_Free(mr->node);
5399
5400         kfree(mr);
5401
5402         MEMORY_LOCK(Os);
5403     }
5404
5405     MEMORY_UNLOCK(Os);
5406
5407     if (i > 0)
5408     {
5409         gcmkTRACE_ZONE(gcvLEVEL_ERROR,
5410                 gcvZONE_OS,
5411                 "======== Total %d unfreed video/contiguous/virtual memory ========", i);
5412     }
5413 }
5414 #endif
5415
5416 /*******************************************************************************
5417 **  gckOS_CacheFlush
5418 **
5419 **  Flush the cache for the specified addresses.  The GPU is going to need the
5420 **  data.  If the system is allocating memory as non-cachable, this function can
5421 **  be ignored.
5422 **
5423 **  ARGUMENTS:
5424 **
5425 **      gckOS Os
5426 **          Pointer to gckOS object.
5427 **
5428 **      gctHANDLE Process
5429 **          Process handle Logical belongs to or gcvNULL if Logical belongs to
5430 **          the kernel.
5431 **
5432 **      gctPOINTER Logical
5433 **          Logical address to flush.
5434 **
5435 **      gctSIZE_T Bytes
5436 **          Size of the address range in bytes to flush.
5437 */
5438 gceSTATUS
5439 gckOS_CacheFlush(
5440     IN gckOS Os,
5441     IN gctHANDLE Process,
5442     IN gctPOINTER Logical,
5443     IN gctSIZE_T Bytes
5444     )
5445 {
5446 #if (1==gcdENABLE_MEM_CACHE)
5447     dmac_clean_range(Logical, Logical+Bytes);
5448 #elif (2==gcdENABLE_MEM_CACHE)
5449     dsb();
5450 #endif
5451     return gcvSTATUS_OK;
5452 }
5453
5454 /*******************************************************************************
5455 **  gckOS_CacheInvalidate
5456 **
5457 **  Flush the cache for the specified addresses and invalidate the lines as
5458 **  well.  The GPU is going to need and modify the data.  If the system is
5459 **  allocating memory as non-cachable, this function can be ignored.
5460 **
5461 **  ARGUMENTS:
5462 **
5463 **      gckOS Os
5464 **          Pointer to gckOS object.
5465 **
5466 **      gctHANDLE Process
5467 **          Process handle Logical belongs to or gcvNULL if Logical belongs to
5468 **          the kernel.
5469 **
5470 **      gctPOINTER Logical
5471 **          Logical address to flush.
5472 **
5473 **      gctSIZE_T Bytes
5474 **          Size of the address range in bytes to flush.
5475 */
5476 gceSTATUS
5477 gckOS_CacheInvalidate(
5478     IN gckOS Os,
5479     IN gctHANDLE Process,
5480     IN gctPOINTER Logical,
5481     IN gctSIZE_T Bytes
5482     )
5483 {
5484 #if (1==gcdENABLE_MEM_CACHE)
5485     dmac_flush_range(Logical, Logical+Bytes);
5486 #elif (2==gcdENABLE_MEM_CACHE)
5487     dsb();
5488 #endif
5489     return gcvSTATUS_OK;
5490 }
5491
5492 /*******************************************************************************
5493 ********************************* Broadcasting *********************************
5494 *******************************************************************************/
5495
5496 /*******************************************************************************
5497 **
5498 **  gckOS_Broadcast
5499 **
5500 **  System hook for broadcast events from the kernel driver.
5501 **
5502 **  INPUT:
5503 **
5504 **      gckOS Os
5505 **          Pointer to the gckOS object.
5506 **
5507 **      gckHARDWARE Hardware
5508 **          Pointer to the gckHARDWARE object.
5509 **
5510 **      gceBROADCAST Reason
5511 **          Reason for the broadcast.  Can be one of the following values:
5512 **
5513 **              gcvBROADCAST_GPU_IDLE
5514 **                  Broadcasted when the kernel driver thinks the GPU might be
5515 **                  idle.  This can be used to handle power management.
5516 **
5517 **              gcvBROADCAST_GPU_COMMIT
5518 **                  Broadcasted when any client process commits a command
5519 **                  buffer.  This can be used to handle power management.
5520 **
5521 **              gcvBROADCAST_GPU_STUCK
5522 **                  Broadcasted when the kernel driver hits the timeout waiting
5523 **                  for the GPU.
5524 **
5525 **              gcvBROADCAST_FIRST_PROCESS
5526 **                  First process is trying to connect to the kernel.
5527 **
5528 **              gcvBROADCAST_LAST_PROCESS
5529 **                  Last process has detached from the kernel.
5530 **
5531 **  OUTPUT:
5532 **
5533 **      Nothing.
5534 */
5535 gceSTATUS
5536 gckOS_Broadcast(
5537     IN gckOS Os,
5538     IN gckHARDWARE Hardware,
5539     IN gceBROADCAST Reason
5540     )
5541 {
5542     gceSTATUS status;
5543     gctUINT32 idle = 0, dma = 0, axi = 0, read0 = 0, read1 = 0, write = 0;
5544     gctUINT32 debugState = 0, memoryDebug = 0;
5545     gctUINT32 debugCmdLow = 0, debugCmdHi = 0;
5546     gctUINT32 i, debugSignalsPe, debugSignalsMc;
5547
5548     gcmkHEADER_ARG("Os=0x%x Hardware=0x%x Reason=%d", Os, Hardware, Reason);
5549
5550     /* Verify the arguments. */
5551     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5552     gcmkVERIFY_OBJECT(Hardware, gcvOBJ_HARDWARE);
5553
5554     switch (Reason)
5555     {
5556     case gcvBROADCAST_FIRST_PROCESS:
5557         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "First process has attached");
5558         break;
5559
5560     case gcvBROADCAST_LAST_PROCESS:
5561         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "Last process has detached");
5562
5563         /* Put GPU OFF. */
5564         gcmkONERROR(
5565             gckHARDWARE_SetPowerManagementState(Hardware,
5566                                                 gcvPOWER_OFF_BROADCAST));
5567         break;
5568
5569     case gcvBROADCAST_GPU_IDLE:
5570         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "GPU idle.");
5571
5572         /* Put GPU IDLE. */
5573         gcmkONERROR(
5574             gckHARDWARE_SetPowerManagementState(Hardware,
5575                                                 gcvPOWER_IDLE_BROADCAST));
5576         break;
5577
5578     case gcvBROADCAST_GPU_COMMIT:
5579         gcmkTRACE_ZONE(gcvLEVEL_INFO, gcvZONE_OS, "COMMIT has arrived.");
5580
5581         /* Put GPU ON. */
5582         gcmkONERROR(
5583             gckHARDWARE_SetPowerManagementState(Hardware,
5584                                                 gcvPOWER_ON_BROADCAST));
5585         break;
5586
5587     case gcvBROADCAST_GPU_STUCK:
5588                 gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
5589         gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
5590                 gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
5591         gcmkPRINT("!!FATAL!! GPU Stuck");
5592         gcmkPRINT("  idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
5593
5594         if (Hardware->chipFeatures & (1 << 4))
5595         {
5596             gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
5597             gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
5598             gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
5599             gcmkPRINT("  read0=0x%08X read1=0x%08X write=0x%08X",
5600                       read0, read1, write);
5601         }
5602
5603         gcmkONERROR(gckOS_ReadRegister(Os, 0x660, &debugState));
5604         gcmkONERROR(gckOS_ReadRegister(Os, 0x414, &memoryDebug));
5605         gcmkPRINT("  debugState(0x660)=0x%08X memoryDebug(0x414)=0x%08X",
5606                   debugState, memoryDebug);
5607
5608         gcmkONERROR(gckOS_ReadRegister(Os, 0x668, &debugCmdLow));
5609         gcmkONERROR(gckOS_ReadRegister(Os, 0x66C, &debugCmdHi));
5610         gcmkPRINT("  debugCmdLow(0x668)=0x%08X debugCmdHi(0x66C)=0x%08X",
5611                   debugCmdLow, debugCmdHi);
5612
5613         for (i = 0; i < 16; i++)
5614         {
5615             gcmkONERROR(gckOS_WriteRegister(Os, 0x470, i << 16));
5616             gcmkPRINT("%d: Write 0x%08X to DebugControl0(0x470)", i, i << 16);
5617
5618             gcmkONERROR(gckOS_ReadRegister(Os, 0x454, &debugSignalsPe));
5619             gcmkPRINT("%d: debugSignalsPe(0x454)=0x%08X", i, debugSignalsPe);
5620
5621             gcmkPRINT("");
5622         }
5623
5624         for (i = 0; i < 16; i++)
5625         {
5626             gcmkONERROR(gckOS_WriteRegister(Os, 0x478, i));
5627             gcmkPRINT("%d: Write 0x%08X to DebugControl2(0x478)", i, i);
5628
5629             gcmkONERROR(gckOS_ReadRegister(Os, 0x468, &debugSignalsMc));
5630             gcmkPRINT("%d: debugSignalsMc(0x468)=0x%08X", i, debugSignalsMc);
5631
5632             gcmkPRINT("");
5633         }
5634
5635
5636         gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
5637         break;
5638
5639     case gcvBROADCAST_AXI_BUS_ERROR:
5640         gcmkONERROR(gckHARDWARE_GetIdle(Hardware, gcvFALSE, &idle));
5641         gcmkONERROR(gckOS_ReadRegister(Os, 0x00C, &axi));
5642         gcmkONERROR(gckOS_ReadRegister(Os, 0x664, &dma));
5643         gcmkPRINT("!!FATAL!! AXI Bus Error");
5644         gcmkPRINT("  idle=0x%08X axi=0x%08X cmd=0x%08X", idle, axi, dma);
5645
5646         if (Hardware->chipFeatures & (1 << 4))
5647         {
5648             gcmkONERROR(gckOS_ReadRegister(Os, 0x43C, &read0));
5649             gcmkONERROR(gckOS_ReadRegister(Os, 0x440, &read1));
5650             gcmkONERROR(gckOS_ReadRegister(Os, 0x444, &write));
5651             gcmkPRINT("  read0=0x%08X read1=0x%08X write=0x%08X",
5652                       read0, read1, write);
5653         }
5654
5655         gcmkONERROR(gckKERNEL_Recovery(Hardware->kernel));
5656         break;
5657     }
5658
5659     /* Success. */
5660     gcmkFOOTER_NO();
5661     return gcvSTATUS_OK;
5662
5663 OnError:
5664     /* Return the status. */
5665     gcmkFOOTER();
5666     return status;
5667 }
5668
5669 /*******************************************************************************
5670 ********************************** Semaphores **********************************
5671 *******************************************************************************/
5672
5673 /*******************************************************************************
5674 **
5675 **  gckOS_CreateSemaphore
5676 **
5677 **  Create a semaphore.
5678 **
5679 **  INPUT:
5680 **
5681 **      gckOS Os
5682 **          Pointer to the gckOS object.
5683 **
5684 **  OUTPUT:
5685 **
5686 **      gctPOINTER * Semaphore
5687 **          Pointer to the variable that will receive the created semaphore.
5688 */
5689 gceSTATUS
5690 gckOS_CreateSemaphore(
5691     IN gckOS Os,
5692     OUT gctPOINTER * Semaphore
5693     )
5694 {
5695     gceSTATUS status;
5696     struct semaphore *sem;
5697
5698     gcmkHEADER_ARG("Os=0x%x", Os);
5699
5700     /* Verify the arguments. */
5701     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5702     gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5703
5704     /* Allocate the semaphore structure. */
5705     gcmkONERROR(
5706         gckOS_Allocate(Os, gcmSIZEOF(struct semaphore), (gctPOINTER *) &sem));
5707
5708     /* Initialize the semaphore. */
5709     sema_init(sem, 1);
5710
5711     /* Return to caller. */
5712     *Semaphore = (gctPOINTER) sem;
5713
5714     /* Success. */
5715     gcmkFOOTER_NO();
5716     return gcvSTATUS_OK;
5717
5718 OnError:
5719     /* Return the status. */
5720     gcmkFOOTER();
5721     return status;
5722 }
5723
5724 /*******************************************************************************
5725 **
5726 **  gckOS_AcquireSemaphore
5727 **
5728 **  Acquire a semaphore.
5729 **
5730 **  INPUT:
5731 **
5732 **      gckOS Os
5733 **          Pointer to the gckOS object.
5734 **
5735 **      gctPOINTER Semaphore
5736 **          Pointer to the semaphore thet needs to be acquired.
5737 **
5738 **  OUTPUT:
5739 **
5740 **      Nothing.
5741 */
5742 gceSTATUS
5743 gckOS_AcquireSemaphore(
5744     IN gckOS Os,
5745     IN gctPOINTER Semaphore
5746     )
5747 {
5748     gceSTATUS status;
5749
5750     gcmkHEADER_ARG("Os=0x%x", Os);
5751
5752     /* Verify the arguments. */
5753     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5754     gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5755
5756     /* Acquire the semaphore. */
5757     if (down_interruptible((struct semaphore *) Semaphore))
5758     {
5759         gcmkONERROR(gcvSTATUS_TIMEOUT);
5760     }
5761
5762     /* Success. */
5763     gcmkFOOTER_NO();
5764     return gcvSTATUS_OK;
5765
5766 OnError:
5767     /* Return the status. */
5768     gcmkFOOTER();
5769     return status;
5770 }
5771
5772 /*******************************************************************************
5773 **
5774 **  gckOS_ReleaseSemaphore
5775 **
5776 **  Release a previously acquired semaphore.
5777 **
5778 **  INPUT:
5779 **
5780 **      gckOS Os
5781 **          Pointer to the gckOS object.
5782 **
5783 **      gctPOINTER Semaphore
5784 **          Pointer to the semaphore thet needs to be released.
5785 **
5786 **  OUTPUT:
5787 **
5788 **      Nothing.
5789 */
5790 gceSTATUS
5791 gckOS_ReleaseSemaphore(
5792     IN gckOS Os,
5793     IN gctPOINTER Semaphore
5794     )
5795 {
5796     gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
5797
5798     /* Verify the arguments. */
5799     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5800     gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5801
5802     /* Release the semaphore. */
5803     up((struct semaphore *) Semaphore);
5804
5805     /* Success. */
5806     gcmkFOOTER_NO();
5807     return gcvSTATUS_OK;
5808 }
5809
5810 /*******************************************************************************
5811 **
5812 **  gckOS_DestroySemaphore
5813 **
5814 **  Destroy a semaphore.
5815 **
5816 **  INPUT:
5817 **
5818 **      gckOS Os
5819 **          Pointer to the gckOS object.
5820 **
5821 **      gctPOINTER Semaphore
5822 **          Pointer to the semaphore thet needs to be destroyed.
5823 **
5824 **  OUTPUT:
5825 **
5826 **      Nothing.
5827 */
5828 gceSTATUS
5829 gckOS_DestroySemaphore(
5830     IN gckOS Os,
5831     IN gctPOINTER Semaphore
5832     )
5833 {
5834     gceSTATUS status;
5835
5836     gcmkHEADER_ARG("Os=0x%x Semaphore=0x%x", Os, Semaphore);
5837
5838      /* Verify the arguments. */
5839     gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
5840     gcmkVERIFY_ARGUMENT(Semaphore != gcvNULL);
5841
5842     /* Free the sempahore structure. */
5843     gcmkONERROR(gckOS_Free(Os, Semaphore));
5844
5845     /* Success. */
5846     gcmkFOOTER_NO();
5847     return gcvSTATUS_OK;
5848
5849 OnError:
5850     /* Return the status. */
5851     gcmkFOOTER();
5852     return status;
5853 }
5854
5855 /*******************************************************************************
5856 **
5857 **  gckOS_GetProcessID
5858 **
5859 **  Get current process ID.
5860 **
5861 **  INPUT:
5862 **
5863 **      Nothing.
5864 **
5865 **  OUTPUT:
5866 **
5867 **      gctUINT32_PTR ProcessID
5868 **          Pointer to the variable that receives the process ID.
5869 */
5870 gceSTATUS
5871 gckOS_GetProcessID(
5872     OUT gctUINT32_PTR ProcessID
5873     )
5874 {
5875     gcmkHEADER();
5876
5877     /* Verify the arguments. */
5878     gcmkVERIFY_ARGUMENT(ProcessID != gcvNULL);
5879
5880     /* Get process ID. */
5881 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
5882     *ProcessID = task_tgid_vnr(current);
5883 #else
5884     *ProcessID = current->tgid;
5885 #endif
5886
5887     /* Success. */
5888     gcmkFOOTER_ARG("*ProcessID=%u", *ProcessID);
5889     return gcvSTATUS_OK;
5890 }
5891
5892 /*******************************************************************************
5893 **
5894 **  gckOS_GetThreadID
5895 **
5896 **  Get current thread ID.
5897 **
5898 **  INPUT:
5899 **
5900 **      Nothing.
5901 **
5902 **  OUTPUT:
5903 **
5904 **      gctUINT32_PTR ThreadID
5905 **          Pointer to the variable that receives the thread ID.
5906 */
5907 gceSTATUS
5908 gckOS_GetThreadID(
5909     OUT gctUINT32_PTR ThreadID
5910     )
5911 {
5912     gcmkHEADER();
5913
5914     /* Verify the arguments. */
5915     gcmkVERIFY_ARGUMENT(ThreadID != gcvNULL);
5916
5917     /* Get thread ID. */
5918 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
5919     *ThreadID = task_pid_vnr(current);
5920 #else
5921     *ThreadID = current->pid;
5922 #endif
5923
5924     /* Success. */
5925     gcmkFOOTER_ARG("*ThreadID=%u", *ThreadID);
5926     return gcvSTATUS_OK;
5927 }
5928
5929 /*******************************************************************************
5930 **
5931 **  gckOS_SetGPUPower
5932 **
5933 **  Set the power of the GPU on or off.
5934 **
5935 **  INPUT:
5936 **
5937 **      gckOS Os
5938 **          Pointer to a gckOS object.
5939 **
5940 **      gctBOOL Clock
5941 **          gcvTRUE to turn on the clock, or gcvFALSE to turn off the clock.
5942 **
5943 **      gctBOOL Power
5944 **          gcvTRUE to turn on the power, or gcvFALSE to turn off the power.
5945 **
5946 **  OUTPUT:
5947 **
5948 **      Nothing.
5949 */
5950 gceSTATUS
5951 gckOS_SetGPUPower(
5952     IN gckOS Os,
5953     IN gctBOOL Clock,
5954     IN gctBOOL Power
5955     )
5956 {
5957     //gcmkHEADER_ARG("Os=0x%x Clock=%d Power=%d", Os, Clock, Power);
5958
5959     /* TODO: Put your code here. */
5960 #if ENABLE_GPU_CLOCK_BY_DRIVER && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28)
5961
5962     struct clk * clk_gpu = clk_get(NULL, "gpu");
5963     struct clk * clk_aclk_gpu = clk_get(NULL, "aclk_gpu");
5964     struct clk * clk_aclk_ddr_gpu = clk_get(NULL, "aclk_ddr_gpu");
5965     struct clk * clk_hclk_gpu = clk_get(NULL, "hclk_gpu");
5966     static int lastpower = 0;
5967     static int lastclock = 0;
5968
5969     //printk("---------- gckOS_SetGPUPower Clock=%d Power=%d \n", Clock, Power);
5970
5971     mdelay(1);
5972     if(lastclock!=Clock) 
5973     {
5974         if(Clock) {
5975             printk("gpu: clk_enable... ");
5976             clk_enable(clk_gpu);
5977             clk_enable(clk_aclk_gpu);
5978             clk_enable(clk_aclk_ddr_gpu);
5979             clk_enable(clk_hclk_gpu);
5980             printk("done!\n");
5981         } else {
5982             printk("gpu: clk_disable... ");
5983             clk_disable(clk_hclk_gpu);
5984             clk_disable(clk_aclk_ddr_gpu);
5985             clk_disable(clk_aclk_gpu);
5986             clk_disable(clk_gpu);
5987             printk("done!\n");
5988         }
5989     }
5990     lastclock = Clock;
5991
5992
5993     mdelay(1);
5994     if(lastpower!=Power)
5995     {
5996         if(Power) {
5997             printk("gpu: power on... ");
5998             if(lastclock)    clk_disable(clk_aclk_ddr_gpu);
5999             mdelay(1);
6000             pmu_set_power_domain(PD_GPU, true);
6001             mdelay(1);
6002             if(lastclock)    clk_enable(clk_aclk_ddr_gpu);
6003             printk("done!\n");
6004         } else {
6005             printk("gpu: power off... ");
6006             pmu_set_power_domain(PD_GPU, false);
6007             printk("done!\n");
6008         }
6009     }
6010     lastpower = Power;
6011
6012     mdelay(1);
6013 #endif
6014
6015     gcmkFOOTER_NO();
6016     return gcvSTATUS_OK;
6017 }
6018