]> code.ossystems Code Review - meta-freescale.git/blob
9c7cd44c8c5a16af427d857490d78d3a8b580249
[meta-freescale.git] /
1 From 46e3a6de5adb9379f9d6eef2c038c2f18637d407 Mon Sep 17 00:00:00 2001
2 From: Loren Huang <b02279@freescale.com>
3 Date: Mon, 25 Mar 2013 15:43:57 +0800
4 Subject: [PATCH 1/6] ENGR00255688 4.6.9p11.1 [gpu]GPU Kernel driver
5  integration
6
7 4.6.9p11.1 GPU kernel driver integration
8 Cherry pick from imx_3.0.35
9
10 Upstream-Status: Backport [3.5.7-1.0.0]
11
12 Signed-off-by: Loren Huang <b02279@freescale.com>
13 Acked-by: Lily Zhang
14 ---
15  drivers/mxc/gpu-viv/Kbuild                         |   2 +-
16  .../arch/XAQ2/hal/kernel/gc_hal_kernel_context.c   |   2 +-
17  .../arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c  |   7 +-
18  drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h     |   2 +-
19  drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c  |  53 ++++--
20  .../mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c   |   5 +-
21  drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c | 178 ++++++++++++---------
22  .../hal/kernel/gc_hal_kernel_video_memory.c        |   3 +-
23  .../gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h    |  13 +-
24  drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h |  25 +++
25  .../mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h    |  35 ++++
26  .../mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h    |   2 +-
27  .../hal/os/linux/kernel/gc_hal_kernel_driver.c     |   2 +-
28  .../hal/os/linux/kernel/gc_hal_kernel_linux.h      |   6 +
29  .../gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c |  82 +++++++++-
30  15 files changed, 304 insertions(+), 113 deletions(-)
31
32 diff --git a/drivers/mxc/gpu-viv/Kbuild b/drivers/mxc/gpu-viv/Kbuild
33 index 0b18a7b..93b1259 100644
34 --- a/drivers/mxc/gpu-viv/Kbuild
35 +++ b/drivers/mxc/gpu-viv/Kbuild
36 @@ -1,6 +1,6 @@
37  ##############################################################################
38  #
39 -#    Copyright (C) 2005 - 2012 by Vivante Corp.
40 +#    Copyright (C) 2005 - 2013 by Vivante Corp.
41  #
42  #    This program is free software; you can redistribute it and/or modify
43  #    it under the terms of the GNU General Public License as published by
44 diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
45 index 22e1f27..24003e7 100644
46 --- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
47 +++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_context.c
48 @@ -471,7 +471,7 @@ _InitializeContextBuffer(
49      index += _SwitchPipe(Context, index, gcvPIPE_3D);
50  
51      /* Current context pointer. */
52 -#if gcdDEBUG 
53 +#if gcdDEBUG
54      index += _State(Context, index, 0x03850 >> 2, 0x00000000, 1, gcvFALSE, gcvFALSE);
55  #endif
56  
57 diff --git a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
58 index a87259e..3829999 100644
59 --- a/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
60 +++ b/drivers/mxc/gpu-viv/arch/XAQ2/hal/kernel/gc_hal_kernel_hardware.c
61 @@ -232,7 +232,8 @@ _IdentifyHardware(
62      }
63  
64      /* Exception for GC1000, revision 5035 &  GC800, revision 4612 */
65 -    if (((Identity->chipModel == gcv1000) && (Identity->chipRevision == 0x5035))
66 +    if (((Identity->chipModel == gcv1000) && ((Identity->chipRevision == 0x5035)
67 +                                           || (Identity->chipRevision == 0x5036)))
68          || ((Identity->chipModel == gcv800) && (Identity->chipRevision == 0x4612)))
69      {
70          Identity->superTileMode = 1;
71 @@ -751,7 +752,7 @@ gckHARDWARE_Construct(
72      /* Initialize the fast clear. */
73      gcmkONERROR(gckHARDWARE_SetFastClear(hardware, -1, -1));
74  
75 -#if !gcdENABLE_128B_MERGE  
76 +#if !gcdENABLE_128B_MERGE
77  
78      if (((((gctUINT32) (hardware->identity.chipMinorFeatures2)) >> (0 ? 21:21) & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1)))))) == (0x1  & ((gctUINT32) ((((1 ? 21:21) - (0 ? 21:21) + 1) == 32) ? ~0 : (~(~0 << ((1 ? 21:21) - (0 ? 21:21) + 1))))))))
79      {
80 @@ -1027,7 +1028,7 @@ gckHARDWARE_InitializeHardware(
81                                        0x00424,
82                                        baseAddress));
83  
84 -#if !VIVANTE_PROFILER 
85 +#if !VIVANTE_PROFILER
86      {
87          gctUINT32 data;
88  
89 diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
90 index 1da80b7..5896e93 100644
91 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
92 +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
93 @@ -186,7 +186,7 @@ typedef struct _gcsDATABASE
94      gctUINT64                           idle;
95  
96      /* Pointer to database. */
97 -    gcsDATABASE_RECORD_PTR              list;
98 +    gcsDATABASE_RECORD_PTR              list[48];
99  
100  #if gcdSECURE_USER
101      /* Secure cache. */
102 diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
103 index 1fb18fb..bc5f083 100644
104 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
105 +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_db.c
106 @@ -26,6 +26,9 @@
107  /*******************************************************************************
108  ***** Private fuctions ********************************************************/
109  
110 +#define _GetSlot(database, x) \
111 +    (gctUINT32)(((gcmPTR_TO_UINT64(x) >> 7) % gcmCOUNTOF(database->list)))
112 +
113  /*******************************************************************************
114  **  gckKERNEL_NewDatabase
115  **
116 @@ -56,6 +59,7 @@ gckKERNEL_NewDatabase(
117      gcsDATABASE_PTR database;
118      gctBOOL acquired = gcvFALSE;
119      gctSIZE_T slot;
120 +    gcsDATABASE_PTR existingDatabase;
121  
122      gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
123  
124 @@ -63,6 +67,21 @@ gckKERNEL_NewDatabase(
125      gcmkONERROR(gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
126      acquired = gcvTRUE;
127  
128 +    /* Compute the hash for the database. */
129 +    slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
130 +
131 +    /* Walk the hash list. */
132 +    for (existingDatabase = Kernel->db->db[slot];
133 +         existingDatabase != gcvNULL;
134 +         existingDatabase = existingDatabase->next)
135 +    {
136 +        if (existingDatabase->processID == ProcessID)
137 +        {
138 +            /* One process can't be added twice. */
139 +            gcmkONERROR(gcvSTATUS_NOT_SUPPORTED);
140 +        }
141 +    }
142 +
143      if (Kernel->db->freeDatabase != gcvNULL)
144      {
145          /* Allocate a database from the free list. */
146 @@ -81,9 +100,6 @@ gckKERNEL_NewDatabase(
147          database = pointer;
148      }
149  
150 -    /* Compute the hash for the database. */
151 -    slot = ProcessID % gcmCOUNTOF(Kernel->db->db);
152 -
153      /* Insert the database into the hash. */
154      database->next   = Kernel->db->db[slot];
155      Kernel->db->db[slot] = database;
156 @@ -350,6 +366,7 @@ static gceSTATUS
157  gckKERNEL_NewRecord(
158      IN gckKERNEL Kernel,
159      IN gcsDATABASE_PTR Database,
160 +    IN gctUINT32 Slot,
161      OUT gcsDATABASE_RECORD_PTR * Record
162      )
163  {
164 @@ -383,8 +400,8 @@ gckKERNEL_NewRecord(
165      }
166  
167      /* Insert the record in the database. */
168 -    record->next   = Database->list;
169 -    Database->list = record;
170 +    record->next         = Database->list[Slot];
171 +    Database->list[Slot] = record;
172  
173      /* Release the database mutex. */
174      gcmkONERROR(gckOS_ReleaseMutex(Kernel->os, Kernel->db->dbMutex));
175 @@ -449,6 +466,7 @@ gckKERNEL_DeleteRecord(
176      gceSTATUS status;
177      gctBOOL acquired = gcvFALSE;
178      gcsDATABASE_RECORD_PTR record, previous;
179 +    gctUINT32 slot = _GetSlot(Database, Data);
180  
181      gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
182                     Kernel, Database, Type, Data);
183 @@ -458,8 +476,9 @@ gckKERNEL_DeleteRecord(
184          gckOS_AcquireMutex(Kernel->os, Kernel->db->dbMutex, gcvINFINITE));
185      acquired = gcvTRUE;
186  
187 +
188      /* Scan the database for this record. */
189 -    for (record = Database->list, previous = gcvNULL;
190 +    for (record = Database->list[slot], previous = gcvNULL;
191           record != gcvNULL;
192           record = record->next
193      )
194 @@ -490,7 +509,7 @@ gckKERNEL_DeleteRecord(
195      /* Remove record from database. */
196      if (previous == gcvNULL)
197      {
198 -        Database->list = record->next;
199 +        Database->list[slot] = record->next;
200      }
201      else
202      {
203 @@ -557,6 +576,7 @@ gckKERNEL_FindRecord(
204      gceSTATUS status;
205      gctBOOL acquired = gcvFALSE;
206      gcsDATABASE_RECORD_PTR record;
207 +    gctUINT32 slot = _GetSlot(Database, Data);
208  
209      gcmkHEADER_ARG("Kernel=0x%x Database=0x%x Type=%d Data=0x%x",
210                     Kernel, Database, Type, Data);
211 @@ -567,7 +587,7 @@ gckKERNEL_FindRecord(
212      acquired = gcvTRUE;
213  
214      /* Scan the database for this record. */
215 -    for (record = Database->list;
216 +    for (record = Database->list[slot];
217           record != gcvNULL;
218           record = record->next
219      )
220 @@ -642,6 +662,7 @@ gckKERNEL_CreateProcessDB(
221  {
222      gceSTATUS status;
223      gcsDATABASE_PTR database = gcvNULL;
224 +    gctUINT32 i;
225  
226      gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
227  
228 @@ -668,7 +689,11 @@ gckKERNEL_CreateProcessDB(
229      database->mapUserMemory.bytes      = 0;
230      database->mapUserMemory.maxBytes   = 0;
231      database->mapUserMemory.totalBytes = 0;
232 -    database->list                  = gcvNULL;
233 +
234 +    for (i = 0; i < gcmCOUNTOF(database->list); i++)
235 +    {
236 +        database->list[i]              = gcvNULL;
237 +    }
238  
239  #if gcdSECURE_USER
240      {
241 @@ -848,7 +873,7 @@ gckKERNEL_AddProcessDB(
242      gcmkONERROR(gckKERNEL_FindDatabase(Kernel, ProcessID, gcvFALSE, &database));
243  
244      /* Create a new record in the database. */
245 -    gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, &record));
246 +    gcmkONERROR(gckKERNEL_NewRecord(Kernel, database, _GetSlot(database, Pointer), &record));
247  
248      /* Initialize the record. */
249      record->kernel   = Kernel;
250 @@ -1086,6 +1111,7 @@ gckKERNEL_DestroyProcessDB(
251      gctPHYS_ADDR physical;
252      gcuVIDMEM_NODE_PTR node;
253      gckKERNEL kernel = Kernel;
254 +    gctUINT32 i;
255  
256      gcmkHEADER_ARG("Kernel=0x%x ProcessID=%d", Kernel, ProcessID);
257  
258 @@ -1126,8 +1152,11 @@ gckKERNEL_DestroyProcessDB(
259                         ProcessID);
260      }
261  
262 +    for(i = 0; i < gcmCOUNTOF(database->list); i++)
263 +    {
264 +
265      /* Walk all records. */
266 -    for (record = database->list; record != gcvNULL; record = next)
267 +    for (record = database->list[i]; record != gcvNULL; record = next)
268      {
269          /* Next next record. */
270          next = record->next;
271 @@ -1293,6 +1322,8 @@ gckKERNEL_DestroyProcessDB(
272                                             gcvNULL));
273      }
274  
275 +    }
276 +
277      /* Delete the database. */
278      gcmkONERROR(gckKERNEL_DeleteDatabase(Kernel, database));
279  
280 diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
281 index f78d096..217f7f1 100644
282 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
283 +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_event.c
284 @@ -959,6 +959,8 @@ gckEVENT_AddList(
285      record->kernel = Event->kernel;
286  #endif
287  
288 +    gcmkONERROR(__RemoveRecordFromProcessDB(Event, record));
289 +
290      /* Acquire the mutex. */
291      gcmkONERROR(gckOS_AcquireMutex(Event->os, Event->eventListMutex, gcvINFINITE));
292      acquired = gcvTRUE;
293 @@ -1539,9 +1541,6 @@ gckEVENT_Submit(
294              gcmkONERROR(gckOS_ReleaseMutex(Event->os, Event->eventListMutex));
295              acquired = gcvFALSE;
296  
297 -            gcmkONERROR(__RemoveRecordFromProcessDB(Event,
298 -                Event->queues[id].head));
299 -
300  #if gcdNULL_DRIVER
301              /* Notify immediately on infinite hardware. */
302              gcmkONERROR(gckEVENT_Interrupt(Event, 1 << id));
303 diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
304 index 0c71e28..43c9297 100644
305 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
306 +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
307 @@ -97,6 +97,43 @@ static gcsMirrorPageTable_PTR mirrorPageTable = gcvNULL;
308  static gctPOINTER mirrorPageTableMutex = gcvNULL;
309  #endif
310  
311 +static void
312 +_WritePageEntry(
313 +    IN gctUINT32_PTR PageEntry,
314 +    IN gctUINT32     EntryValue
315 +    )
316 +{
317 +    static gctUINT16 data = 0xff00;
318 +
319 +    if (*(gctUINT8 *)&data == 0xff)
320 +    {
321 +        *PageEntry = gcmSWAB32(EntryValue);
322 +    }
323 +    else
324 +    {
325 +        *PageEntry = EntryValue;
326 +    }
327 +}
328 +
329 +static gctUINT32
330 +_ReadPageEntry(
331 +    IN gctUINT32_PTR PageEntry
332 +    )
333 +{
334 +    static gctUINT16 data = 0xff00;
335 +    gctUINT32 entryValue;
336 +
337 +    if (*(gctUINT8 *)&data == 0xff)
338 +    {
339 +        entryValue = *PageEntry;
340 +        return gcmSWAB32(entryValue);
341 +    }
342 +    else
343 +    {
344 +        return *PageEntry;
345 +    }
346 +}
347 +
348  static gceSTATUS
349  _FillPageTable(
350      IN gctUINT32_PTR PageTable,
351 @@ -108,7 +145,7 @@ _FillPageTable(
352  
353      for (i = 0; i < PageCount; i++)
354      {
355 -        PageTable[i] = EntryValue;
356 +        _WritePageEntry(PageTable + i, EntryValue);
357      }
358  
359      return gcvSTATUS_OK;
360 @@ -132,16 +169,16 @@ _Link(
361          gctUINT32_PTR pageTable = Mmu->pageTableLogical;
362  
363          /* Dispatch on node type. */
364 -        switch (gcmENTRY_TYPE(pageTable[Index]))
365 +        switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[Index])))
366          {
367          case gcvMMU_SINGLE:
368              /* Set single index. */
369 -            pageTable[Index] = (Next << 8) | gcvMMU_SINGLE;
370 +            _WritePageEntry(&pageTable[Index], (Next << 8) | gcvMMU_SINGLE);
371              break;
372  
373          case gcvMMU_FREE:
374              /* Set index. */
375 -            pageTable[Index + 1] = Next;
376 +            _WritePageEntry(&pageTable[Index + 1], Next);
377              break;
378  
379          default:
380 @@ -167,13 +204,13 @@ _AddFree(
381      if (Count == 1)
382      {
383          /* Initialize a single page node. */
384 -        pageTable[Node] = (~((1U<<8)-1)) | gcvMMU_SINGLE;
385 +        _WritePageEntry(pageTable + Node, (~((1U<<8)-1)) | gcvMMU_SINGLE);
386      }
387      else
388      {
389          /* Initialize the node. */
390 -        pageTable[Node + 0] = (Count << 8) | gcvMMU_FREE;
391 -        pageTable[Node + 1] = ~0U;
392 +        _WritePageEntry(pageTable + Node + 0, (Count << 8) | gcvMMU_FREE);
393 +        _WritePageEntry(pageTable + Node + 1, ~0U);
394      }
395  
396      /* Append the node. */
397 @@ -196,7 +233,7 @@ _Collect(
398      for (i = 0; i < Mmu->pageTableEntries; ++i)
399      {
400          /* Dispatch based on type of page. */
401 -        switch (gcmENTRY_TYPE(pageTable[i]))
402 +        switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[i])))
403          {
404          case gcvMMU_USED:
405              /* Used page, so close any open node. */
406 @@ -229,10 +266,10 @@ _Collect(
407              }
408  
409              /* Advance the count. */
410 -            count += pageTable[i] >> 8;
411 +            count += _ReadPageEntry(&pageTable[i]) >> 8;
412  
413              /* Advance the index into the page table. */
414 -            i     += (pageTable[i] >> 8) - 1;
415 +            i     += (_ReadPageEntry(&pageTable[i]) >> 8) - 1;
416              break;
417  
418          default:
419 @@ -341,19 +378,20 @@ _FillFlatMapping(
420                  gcmkONERROR(gcvSTATUS_NOT_ALIGNED);
421              }
422  
423 -            *(Mmu->mtlbLogical + mStart)
424 -                      = stlb->physBase
425 -                        /* 64KB page size */
426 -                        | (1 << 2)
427 -                        /* Ignore exception */
428 -                        | (0 << 1)
429 -                        /* Present */
430 -                        | (1 << 0);
431 +            _WritePageEntry(Mmu->mtlbLogical + mStart,
432 +                            stlb->physBase
433 +                            /* 64KB page size */
434 +                            | (1 << 2)
435 +                            /* Ignore exception */
436 +                            | (0 << 1)
437 +                            /* Present */
438 +                            | (1 << 0)
439 +                            );
440  #if gcdMMU_TABLE_DUMP
441              gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
442                  __FUNCTION__, __LINE__,
443                  mStart,
444 -                *(Mmu->mtlbLogical + mStart));
445 +                _ReadPageEntry(Mmu->mtlbLogical + mStart));
446  #endif
447  
448              stlb->mtlbIndex = mStart;
449 @@ -368,12 +406,12 @@ _FillFlatMapping(
450              while (sStart <= last)
451              {
452                  gcmkASSERT(!(start & gcdMMU_PAGE_64K_MASK));
453 -                *(stlb->logical + sStart) = _SetPage(start);
454 +                _WritePageEntry(stlb->logical + sStart, _SetPage(start));
455  #if gcdMMU_TABLE_DUMP
456                  gckOS_Print("%s(%d): insert STLB[%d]: %08x\n",
457                      __FUNCTION__, __LINE__,
458                      sStart,
459 -                    *(stlb->logical + sStart));
460 +                    _ReadPageEntry(stlb->logical + sStart));
461  #endif
462                  /* next page. */
463                  start += gcdMMU_PAGE_64K_SIZE;
464 @@ -428,7 +466,7 @@ OnError:
465          if (pre->mtlbEntryNum != 0)
466          {
467              gcmkASSERT(pre->mtlbEntryNum == 1);
468 -            *(Mmu->mtlbLogical + pre->mtlbIndex) = 0;
469 +            _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
470          }
471  
472          gcmkVERIFY_OK(gcmkOS_SAFE_FREE(Mmu->os, pre));
473 @@ -493,8 +531,8 @@ _SetupDynamicSpace(
474  
475      /* Initilization. */
476      pageTable      = Mmu->pageTableLogical;
477 -    pageTable[0]   = (Mmu->pageTableEntries << 8) | gcvMMU_FREE;
478 -    pageTable[1]   = ~0U;
479 +    _WritePageEntry(pageTable,     (Mmu->pageTableEntries << 8) | gcvMMU_FREE);
480 +    _WritePageEntry(pageTable + 1, ~0U);
481      Mmu->heapList  = 0;
482      Mmu->freeNodes = gcvFALSE;
483  
484 @@ -509,18 +547,20 @@ _SetupDynamicSpace(
485      /* Map to Master TLB. */
486      for (; i < gcdMMU_MTLB_ENTRY_NUM; i++)
487      {
488 -        Mmu->mtlbLogical[i] = physical
489 -                            /* 4KB page size */
490 -                            | (0 << 2)
491 -                            /* Ignore exception */
492 -                            | (0 << 1)
493 -                            /* Present */
494 -                            | (1 << 0);
495 +        _WritePageEntry(Mmu->mtlbLogical + i,
496 +                        physical
497 +                        /* 4KB page size */
498 +                        | (0 << 2)
499 +                        /* Ignore exception */
500 +                        | (0 << 1)
501 +                        /* Present */
502 +                        | (1 << 0)
503 +                        );
504  #if gcdMMU_TABLE_DUMP
505          gckOS_Print("%s(%d): insert MTLB[%d]: %08x\n",
506                  __FUNCTION__, __LINE__,
507                  i,
508 -                *(Mmu->mtlbLogical + i));
509 +                _ReadPageEntry(Mmu->mtlbLogical + i));
510  #endif
511          physical += gcdMMU_STLB_4K_SIZE;
512      }
513 @@ -645,18 +685,11 @@ _Construct(
514          pageTable      = mmu->pageTableLogical;
515  
516  #if gcdMMU_CLEAR_VALUE
517 -        {
518 -            gctUINT32 i;
519 -
520 -            for (i = 0; i < mmu->pageTableEntries; ++i)
521 -            {
522 -                pageTable[i] = gcdMMU_CLEAR_VALUE;
523 -            }
524 -        }
525 +        _FillPageTable(pageTable, mmu->pageTableEntries, gcdMMU_CLEAR_VALUE);
526  #endif
527  
528 -        pageTable[0]   = (mmu->pageTableEntries << 8) | gcvMMU_FREE;
529 -        pageTable[1]   = ~0U;
530 +        _WritePageEntry(pageTable,     (mmu->pageTableEntries << 8) | gcvMMU_FREE);
531 +        _WritePageEntry(pageTable + 1, ~0U);
532          mmu->heapList  = 0;
533          mmu->freeNodes = gcvFALSE;
534  
535 @@ -797,7 +830,7 @@ _Destroy(
536          if (pre->mtlbEntryNum != 0)
537          {
538              gcmkASSERT(pre->mtlbEntryNum == 1);
539 -            *(Mmu->mtlbLogical + pre->mtlbIndex) = 0;
540 +            _WritePageEntry(Mmu->mtlbLogical + pre->mtlbIndex, 0);
541  #if gcdMMU_TABLE_DUMP
542              gckOS_Print("%s(%d): clean MTLB[%d]\n",
543                  __FUNCTION__, __LINE__,
544 @@ -1044,7 +1077,7 @@ _AllocatePages(
545          for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
546          {
547              /* Check the node type. */
548 -            switch (gcmENTRY_TYPE(pageTable[index]))
549 +            switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
550              {
551              case gcvMMU_SINGLE:
552                  /* Single odes are valid if we only need 1 page. */
553 @@ -1056,13 +1089,13 @@ _AllocatePages(
554                  {
555                      /* Move to next node. */
556                      previous = index;
557 -                    index    = pageTable[index] >> 8;
558 +                    index    = _ReadPageEntry(&pageTable[index]) >> 8;
559                  }
560                  break;
561  
562              case gcvMMU_FREE:
563                  /* Test if the node has enough space. */
564 -                if (PageCount <= (pageTable[index] >> 8))
565 +                if (PageCount <= (_ReadPageEntry(&pageTable[index]) >> 8))
566                  {
567                      gotIt = gcvTRUE;
568                  }
569 @@ -1070,7 +1103,7 @@ _AllocatePages(
570                  {
571                      /* Move to next node. */
572                      previous = index;
573 -                    index    = pageTable[index + 1];
574 +                    index    = _ReadPageEntry(&pageTable[index + 1]);
575                  }
576                  break;
577  
578 @@ -1099,36 +1132,36 @@ _AllocatePages(
579          }
580      }
581  
582 -    switch (gcmENTRY_TYPE(pageTable[index]))
583 +    switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
584      {
585      case gcvMMU_SINGLE:
586          /* Unlink single node from free list. */
587          gcmkONERROR(
588 -            _Link(Mmu, previous, pageTable[index] >> 8));
589 +            _Link(Mmu, previous, _ReadPageEntry(&pageTable[index]) >> 8));
590          break;
591  
592      case gcvMMU_FREE:
593          /* Check how many pages will be left. */
594 -        left = (pageTable[index] >> 8) - PageCount;
595 +        left = (_ReadPageEntry(&pageTable[index]) >> 8) - PageCount;
596          switch (left)
597          {
598          case 0:
599              /* The entire node is consumed, just unlink it. */
600              gcmkONERROR(
601 -                _Link(Mmu, previous, pageTable[index + 1]));
602 +                _Link(Mmu, previous, _ReadPageEntry(&pageTable[index + 1])));
603              break;
604  
605          case 1:
606              /* One page will remain.  Convert the node to a single node and
607              ** advance the index. */
608 -            pageTable[index] = (pageTable[index + 1] << 8) | gcvMMU_SINGLE;
609 +            _WritePageEntry(&pageTable[index], (_ReadPageEntry(&pageTable[index + 1]) << 8) | gcvMMU_SINGLE);
610              index ++;
611              break;
612  
613          default:
614              /* Enough pages remain for a new node.  However, we will just adjust
615              ** the size of the current node and advance the index. */
616 -            pageTable[index] = (left << 8) | gcvMMU_FREE;
617 +            _WritePageEntry(&pageTable[index], (left << 8) | gcvMMU_FREE);
618              index += left;
619              break;
620          }
621 @@ -1232,35 +1265,32 @@ _FreePages(
622  #if gcdMMU_CLEAR_VALUE
623      if (Mmu->hardware->mmuVersion == 0)
624      {
625 -        gctUINT32 i;
626 -
627 -        for (i = 0; i < PageCount; ++i)
628 -        {
629 -            pageTable[i] = gcdMMU_CLEAR_VALUE;
630 -        }
631 +        _FillPageTable(pageTable, PageCount, gcdMMU_CLEAR_VALUE);
632      }
633  #endif
634  
635      if (PageCount == 1)
636      {
637          /* Single page node. */
638 -        pageTable[0] = (~((1U<<8)-1)) | gcvMMU_SINGLE
639 +        _WritePageEntry(pageTable,
640 +                        (~((1U<<8)-1)) | gcvMMU_SINGLE
641  #if gcdUSE_MMU_EXCEPTION
642 -                     /* Enable exception */
643 -                     | (1 << 1)
644 +                        /* Enable exception */
645 +                        | 1 << 1
646  #endif
647 -                     ;
648 +                        );
649      }
650      else
651      {
652          /* Mark the node as free. */
653 -        pageTable[0] = (PageCount << 8) | gcvMMU_FREE
654 +        _WritePageEntry(pageTable,
655 +                        (PageCount << 8) | gcvMMU_FREE
656  #if gcdUSE_MMU_EXCEPTION
657 -                     /* Enable exception */
658 -                     | (1 << 1)
659 +                        /* Enable exception */
660 +                        | 1 << 1
661  #endif
662 -                     ;
663 -        pageTable[1] = ~0U;
664 +                       );
665 +        _WritePageEntry(pageTable + 1, ~0U);
666  
667  #if gcdUSE_MMU_EXCEPTION
668          /* Enable exception */
669 @@ -1509,12 +1539,8 @@ gckMMU_SetPage(
670          data = _SetPage(PageAddress);
671      }
672  
673 -    if (Mmu->hardware->bigEndian)
674 -    {
675 -        data = gcmSWAB32(data);
676 -    }
677 +    _WritePageEntry(PageEntry, data);
678  
679 -    *PageEntry = data;
680  #if gcdMIRROR_PAGETABLE
681      for (i = 0; i < mirrorPageTable->reference; i++)
682      {
683 @@ -1526,11 +1552,11 @@ gckMMU_SetPage(
684  
685              if (mmu->hardware->mmuVersion == 0)
686              {
687 -                *pageEntry = PageAddress;
688 +                _WritePageEntry(pageEntry, PageAddress);
689              }
690              else
691              {
692 -                *pageEntry = _SetPage(PageAddress);
693 +                _WritePageEntry(pageEntry, _SetPage(PageAddress));
694              }
695          }
696  
697 @@ -1734,7 +1760,7 @@ gckMMU_DumpPageTableEntry(
698                * gcdMMU_STLB_4K_ENTRY_NUM
699                + stlb;
700  
701 -        gcmkPRINT("    Page table entry = 0x%08X", pageTable[index]);
702 +        gcmkPRINT("    Page table entry = 0x%08X", _ReadPageEntry(pageTable + index));
703      }
704  
705      gcmkFOOTER_NO();
706 diff --git a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
707 index d49aa64..8a442a2 100644
708 --- a/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
709 +++ b/drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
710 @@ -1027,7 +1027,8 @@ gckVIDMEM_AllocateLinear(
711      )
712      {
713          /* The left memory is for small memory.*/
714 -        gcmkONERROR(gcvSTATUS_OUT_OF_MEMORY);
715 +        status = gcvSTATUS_OUT_OF_MEMORY;
716 +        goto OnError;
717      }
718  #endif
719  
720 diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
721 index 496276e..06eea79 100644
722 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
723 +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_eglplatform.h
724 @@ -227,7 +227,8 @@ gcoOS_GetDisplayInfoEx(
725      );
726  
727  gceSTATUS
728 -gcoOS_GetNextDisplayInfoEx(
729 +gcoOS_GetNextDisplayInfoExByIndex(
730 +    IN gctINT Index,
731      IN HALNativeDisplayType Display,
732      IN HALNativeWindowType Window,
733      IN gctUINT DisplayInfoSize,
734 @@ -274,15 +275,15 @@ gcoOS_SetDisplayVirtualEx(
735  
736  gceSTATUS
737  gcoOS_SetSwapInterval(
738 -       IN HALNativeDisplayType Display,
739 -       IN gctINT Interval
740 +    IN HALNativeDisplayType Display,
741 +    IN gctINT Interval
742  );
743  
744  gceSTATUS
745  gcoOS_GetSwapInterval(
746 -       IN HALNativeDisplayType Display,
747 -       IN gctINT_PTR Min,
748 -       IN gctINT_PTR Max
749 +    IN HALNativeDisplayType Display,
750 +    IN gctINT_PTR Min,
751 +    IN gctINT_PTR Max
752  );
753  
754  gceSTATUS
755 diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
756 index d441d1d..249b61b 100644
757 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
758 +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_engine.h
759 @@ -1430,6 +1430,16 @@ typedef enum _gceTEXTURE_FACE
760  }
761  gceTEXTURE_FACE;
762  
763 +#if gcdFORCE_MIPMAP
764 +typedef enum
765 +{
766 +    gcvForceMipDisabled  = 0,
767 +    gcvForceMipEnable    = 1,
768 +    gcvForceMipGenerated = 2,
769 +    gcvForceMipNever     = 3,
770 +}gceFORCE_MIPMAP;
771 +#endif
772 +
773  typedef struct _gcsTEXTURE
774  {
775      /* Addressing modes. */
776 @@ -1446,6 +1456,10 @@ typedef struct _gcsTEXTURE
777      gceTEXTURE_FILTER           mipFilter;
778      gctUINT                     anisoFilter;
779      gctBOOL                     forceTopLevel;
780 +    gctBOOL                     autoMipmap;
781 +#if gcdFORCE_MIPMAP
782 +    gceFORCE_MIPMAP             forceMipmap;
783 +#endif
784      /* Level of detail. */
785      gctFIXED_POINT              lodBias;
786      gctFIXED_POINT              lodMin;
787 @@ -1479,7 +1493,18 @@ gceSTATUS
788  gcoTEXTURE_Destroy(
789      IN gcoTEXTURE Texture
790      );
791 +#if gcdFORCE_MIPMAP
792 +gceSTATUS
793 +gcoTEXTURE_DestroyForceMipmap(
794 +    IN gcoTEXTURE Texture
795 +    );
796  
797 +gceSTATUS
798 +gcoTEXTURE_GetMipLevels(
799 +    IN gcoTEXTURE Texture,
800 +    OUT gctINT * levels
801 +    );
802 +#endif
803  /* Replace a mipmap in gcoTEXTURE object. */
804  gceSTATUS
805  gcoTEXTURE_ReplaceMipMap(
806 diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
807 index 86e9133..afe83d0 100644
808 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
809 +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_options.h
810 @@ -114,6 +114,30 @@
811  #define COMMAND_PROCESSOR_VERSION               1
812  
813  /*
814 +    gcdDUMP_KEY
815 +
816 +        Set this to a string that appears in 'cat /proc/<pid>/cmdline'. E.g. 'camera'.
817 +        HAL will create dumps for the processes matching this key.
818 +*/
819 +#ifndef gcdDUMP_KEY
820 +#   define gcdDUMP_KEY                          "process"
821 +#endif
822 +
823 +/*
824 +    gcdDUMP_PATH
825 +
826 +        The dump file location. Some processes cannot write to the sdcard.
827 +        Try apps' data dir, e.g. /data/data/com.android.launcher
828 +*/
829 +#ifndef gcdDUMP_PATH
830 +#if defined(ANDROID)
831 +#   define gcdDUMP_PATH                         "/mnt/sdcard/"
832 +#else
833 +#   define gcdDUMP_PATH                         "./"
834 +#endif
835 +#endif
836 +
837 +/*
838      gcdDUMP
839  
840          When set to 1, a dump of all states and memory uploads, as well as other
841 @@ -342,6 +366,17 @@
842  #endif
843  
844  /*
845 +    gcdUSER_HEAP_ALLOCATOR
846 +
847 +        Set to 1 to enable user mode heap allocator for fast memory allocation
848 +        and destroying. Otherwise, memory allocation/destroying in user mode
849 +        will be directly managed by system. Only for linux for now.
850 +*/
851 +#ifndef gcdUSER_HEAP_ALLOCATOR
852 +#   define gcdUSER_HEAP_ALLOCATOR               1
853 +#endif
854 +
855 +/*
856      gcdHEAP_SIZE
857  
858          Set the allocation size for the internal heaps.  Each time a heap is
859 diff --git a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
860 index 2881604..808fde0 100644
861 --- a/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
862 +++ b/drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_version.h
863 @@ -28,7 +28,7 @@
864  
865  #define gcvVERSION_PATCH        9
866  
867 -#define gcvVERSION_BUILD     1210
868 +#define gcvVERSION_BUILD     4651
869  
870  #define gcvVERSION_DATE      __DATE__
871  
872 diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
873 index 4e3819c..2ed3d0e 100644
874 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
875 +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_driver.c
876 @@ -663,7 +663,7 @@ static int drv_mmap(
877  
878  #if !gcdPAGED_MEMORY_CACHEABLE
879      vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
880 -    vma->vm_flags    |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND;
881 +    vma->vm_flags    |= gcdVM_FLAGS;
882  #endif
883      vma->vm_pgoff     = 0;
884  
885 diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
886 index 9c0bcd5..3c148f6 100644
887 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
888 +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_linux.h
889 @@ -73,6 +73,12 @@
890  
891  #define GetPageCount(size, offset)     ((((size) + ((offset) & ~PAGE_CACHE_MASK)) + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT)
892  
893 +#if LINUX_VERSION_CODE >= KERNEL_VERSION (3,7,0)
894 +#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_DONTDUMP)
895 +#else
896 +#define gcdVM_FLAGS (VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED)
897 +#endif
898 +
899  static inline gctINT
900  GetOrder(
901         IN gctINT numPages
902 diff --git a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
903 index c07ded8..9c2bae6 100644
904 --- a/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
905 +++ b/drivers/mxc/gpu-viv/hal/os/linux/kernel/gc_hal_kernel_os.c
906 @@ -869,6 +869,60 @@ _UnmapUserLogical(
907  #endif
908  }
909  
910 +gceSTATUS
911 +_QueryProcessPageTable(
912 +    IN gctPOINTER Logical,
913 +    OUT gctUINT32 * Address
914 +    )
915 +{
916 +    spinlock_t *lock;
917 +    gctUINTPTR_T logical = (gctUINTPTR_T)Logical;
918 +    pgd_t *pgd;
919 +    pud_t *pud;
920 +    pmd_t *pmd;
921 +    pte_t *pte;
922 +
923 +    if (!current->mm)
924 +    {
925 +        return gcvSTATUS_NOT_FOUND;
926 +    }
927 +
928 +    pgd = pgd_offset(current->mm, logical);
929 +    if (pgd_none(*pgd) || pgd_bad(*pgd))
930 +    {
931 +        return gcvSTATUS_NOT_FOUND;
932 +    }
933 +
934 +    pud = pud_offset(pgd, logical);
935 +    if (pud_none(*pud) || pud_bad(*pud))
936 +    {
937 +        return gcvSTATUS_NOT_FOUND;
938 +    }
939 +
940 +    pmd = pmd_offset(pud, logical);
941 +    if (pmd_none(*pmd) || pmd_bad(*pmd))
942 +    {
943 +        return gcvSTATUS_NOT_FOUND;
944 +    }
945 +
946 +    pte = pte_offset_map_lock(current->mm, pmd, logical, &lock);
947 +    if (!pte)
948 +    {
949 +        return gcvSTATUS_NOT_FOUND;
950 +    }
951 +
952 +    if (!pte_present(*pte))
953 +    {
954 +        pte_unmap_unlock(pte, lock);
955 +        return gcvSTATUS_NOT_FOUND;
956 +    }
957 +
958 +    *Address = (pte_pfn(*pte) << PAGE_SHIFT) | (logical & ~PAGE_MASK);
959 +    pte_unmap_unlock(pte, lock);
960 +
961 +    return gcvSTATUS_OK;
962 +}
963 +
964  /*******************************************************************************
965  **
966  **  gckOS_Construct
967 @@ -1106,6 +1160,9 @@ _CreateKernelVirtualMapping(
968                      numPages,
969                      0,
970                      PAGE_KERNEL);
971 +
972 +        /* Trigger a page fault. */
973 +        memset(addr, 0, numPages * PAGE_SIZE);
974      }
975  #else
976      struct page ** pages;
977 @@ -1136,6 +1193,9 @@ _CreateKernelVirtualMapping(
978      /* ioremap() can't work on system memory since 2.6.38. */
979      addr = vmap(pages, numPages, 0, gcmkNONPAGED_MEMROY_PROT(PAGE_KERNEL));
980  
981 +    /* Trigger a page fault. */
982 +    memset(addr, 0, numPages * PAGE_SIZE);
983 +
984      if (free)
985      {
986          kfree(pages);
987 @@ -1540,7 +1600,7 @@ gckOS_MapMemory(
988  #else
989  #if !gcdPAGED_MEMORY_CACHEABLE
990          mdlMap->vma->vm_page_prot = gcmkPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
991 -        mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
992 +        mdlMap->vma->vm_flags |= gcdVM_FLAGS;
993  #   endif
994          mdlMap->vma->vm_pgoff = 0;
995  
996 @@ -1987,7 +2047,7 @@ gckOS_AllocateNonPagedMemory(
997          }
998  #else
999          mdlMap->vma->vm_page_prot = gcmkNONPAGED_MEMROY_PROT(mdlMap->vma->vm_page_prot);
1000 -        mdlMap->vma->vm_flags |= VM_IO | VM_DONTCOPY | VM_DONTEXPAND | VM_RESERVED;
1001 +        mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1002          mdlMap->vma->vm_pgoff = 0;
1003  
1004          if (remap_pfn_range(mdlMap->vma,
1005 @@ -2367,12 +2427,18 @@ gckOS_GetPhysicalAddress(
1006      gcmkVERIFY_OBJECT(Os, gcvOBJ_OS);
1007      gcmkVERIFY_ARGUMENT(Address != gcvNULL);
1008  
1009 -    /* Get current process ID. */
1010 -    processID = _GetProcessID();
1011 +    /* Query page table of current process first. */
1012 +    status = _QueryProcessPageTable(Logical, Address);
1013  
1014 -    /* Route through other function. */
1015 -    gcmkONERROR(
1016 -        gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
1017 +    if (gcmIS_ERROR(status))
1018 +    {
1019 +        /* Get current process ID. */
1020 +        processID = _GetProcessID();
1021 +
1022 +        /* Route through other function. */
1023 +        gcmkONERROR(
1024 +            gckOS_GetPhysicalAddressProcess(Os, Logical, processID, Address));
1025 +    }
1026  
1027      /* Success. */
1028      gcmkFOOTER_ARG("*Address=0x%08x", *Address);
1029 @@ -4139,7 +4205,7 @@ gckOS_LockPages(
1030              return gcvSTATUS_OUT_OF_RESOURCES;
1031          }
1032  
1033 -        mdlMap->vma->vm_flags |= VM_RESERVED;
1034 +        mdlMap->vma->vm_flags |= gcdVM_FLAGS;
1035  #if !gcdPAGED_MEMORY_CACHEABLE
1036          if (Cacheable == gcvFALSE)
1037          {
1038 -- 
1039 1.8.3.2
1040