]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
ENGR00294354 gpu:Using vitural memory cause AXI bus error
authorLoren Huang <b02279@freescale.com>
Thu, 9 Jan 2014 09:38:37 +0000 (17:38 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Mon, 16 Jun 2014 16:09:37 +0000 (18:09 +0200)
There are two possible reasons to cause AXI bus error
1.Allocate Tile status buffer from virtual memory. It seems gc2000
and gc880 doesn't support tile status buffer from virtual memory.
2.Stream buffer using very beginning gpu mmu address. In this condition,
a faked non gpu mmu address maybe generated and fill into gpu which cause
AXI bus error.

[DATE]09-01-2014
Signed-off-by: Loren Huang <b02279@freescale.com>
Acked-by: Shawn Guo
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel.h
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_mmu.c
drivers/mxc/gpu-viv/hal/kernel/gc_hal_kernel_video_memory.c
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal.h
drivers/mxc/gpu-viv/hal/kernel/inc/gc_hal_enum.h

index 88535488b9164e06a1850fc3aeb1680d225f92df..b75e7f64030ebd6c44535b1d68be1baa50fc93f7 100644 (file)
@@ -933,6 +933,7 @@ gckKERNEL_Dispatch(
 #if !USE_NEW_LINUX_SIGNAL
     gctSIGNAL   signal;
 #endif
+    gceSURF_TYPE type;
 
     gcmkHEADER_ARG("Kernel=0x%x FromUser=%d Interface=0x%x",
                    Kernel, FromUser, Interface);
@@ -1169,6 +1170,8 @@ gckKERNEL_Dispatch(
         break;
 
     case gcvHAL_ALLOCATE_LINEAR_VIDEO_MEMORY:
+        type = Interface->u.AllocateLinearVideoMemory.type;
+
         /* Allocate memory. */
         gcmkONERROR(
             _AllocateMemory(Kernel,
@@ -1181,6 +1184,7 @@ gckKERNEL_Dispatch(
         if (node->VidMem.memory->object.type == gcvOBJ_VIDMEM)
         {
             bytes = node->VidMem.bytes;
+            node->VidMem.type = type;
 
             gcmkONERROR(
                 gckKERNEL_AddProcessDB(Kernel,
@@ -1192,6 +1196,7 @@ gckKERNEL_Dispatch(
         else
         {
             bytes = node->Virtual.bytes;
+            node->Virtual.type = type;
 
             if(node->Virtual.contiguous)
             {
index 6126bae3201d52c4eb246143792c71bb21654c88..d7ff9cf16372a59913db9c575ab161ca0d9b0aae 100644 (file)
@@ -734,6 +734,9 @@ typedef union _gcuVIDMEM_NODE
 #if gcdDYNAMIC_MAP_RESERVED_MEMORY && gcdENABLE_VG
         gctPOINTER              kernelVirtual;
 #endif
+
+        /* Surface type. */
+        gceSURF_TYPE            type;
     }
     VidMem;
 
@@ -790,6 +793,9 @@ typedef union _gcuVIDMEM_NODE
 
         /* */
         gcsVIDMEM_NODE_SHARED_INFO sharedInfo;
+
+        /* Surface type. */
+        gceSURF_TYPE            type;
     }
     Virtual;
 }
index e4ca49725dce4f2b5a300064a5cde377b8bc2816..456ec246241e789eb7532225bd05de175e5ee2f6 100644 (file)
@@ -46,6 +46,9 @@ gceMMU_TYPE;
 #   define gcdMMU_CLEAR_VALUE                   0x00000ABC
 #endif
 
+/* VIV: Start GPU address for gcvSURF_VERTEX.  */
+#define gcdVERTEX_START      (128 << 10)
+
 typedef struct _gcsMMU_STLB *gcsMMU_STLB_PTR;
 
 typedef struct _gcsMMU_STLB
@@ -973,6 +976,88 @@ _Destroy(
     return gcvSTATUS_OK;
 }
 
+/*******************************************************************************
+** _AdjstIndex
+**
+**  Adjust the index from which we search for a usable node to make sure
+**  index allocated is greater than Start.
+*/
+gceSTATUS
+_AdjustIndex(
+    IN gckMMU Mmu,
+    IN gctUINT32 Index,
+    IN gctUINT32 PageCount,
+    IN gctUINT32 Start,
+    OUT gctUINT32 * IndexAdjusted
+    )
+{
+    gceSTATUS status;
+    gctUINT32 index = Index;
+    gctUINT32_PTR map = Mmu->pageTableLogical;
+
+    gcmkHEADER();
+
+    for (; index < Mmu->pageTableEntries;)
+    {
+        gctUINT32 result = 0;
+        gctUINT32 nodeSize = 0;
+
+        if (index >= Start)
+        {
+            break;
+        }
+
+        switch (gcmENTRY_TYPE(map[index]))
+        {
+        case gcvMMU_SINGLE:
+            nodeSize = 1;
+            break;
+
+        case gcvMMU_FREE:
+            nodeSize = map[index] >> 8;
+            break;
+
+        default:
+            gcmkFATAL("MMU table correcupted at index %u!", index);
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+
+        if (nodeSize > PageCount)
+        {
+            result = index + (nodeSize - PageCount);
+
+            if (result >= Start)
+            {
+                break;
+            }
+        }
+
+        switch (gcmENTRY_TYPE(map[index]))
+        {
+        case gcvMMU_SINGLE:
+            index = map[index] >> 8;
+            break;
+
+        case gcvMMU_FREE:
+            index = map[index + 1];
+            break;
+
+        default:
+            gcmkFATAL("MMU table correcupted at index %u!", index);
+            gcmkONERROR(gcvSTATUS_OUT_OF_RESOURCES);
+        }
+    }
+
+    *IndexAdjusted = index;
+
+    gcmkFOOTER_NO();
+    return gcvSTATUS_OK;
+
+OnError:
+    gcmkFOOTER();
+    return status;
+}
+
 gceSTATUS
 gckMMU_Construct(
     IN gckKERNEL Kernel,
@@ -1136,6 +1221,7 @@ gceSTATUS
 _AllocatePages(
     IN gckMMU Mmu,
     IN gctSIZE_T PageCount,
+    IN gceSURF_TYPE Type,
     OUT gctPOINTER * PageTable,
     OUT gctUINT32 * Address
     )
@@ -1170,8 +1256,21 @@ _AllocatePages(
     /* Cast pointer to page table. */
     for (pageTable = Mmu->pageTableLogical, gotIt = gcvFALSE; !gotIt;)
     {
+        index = Mmu->heapList;
+
+        if ((Mmu->hardware->mmuVersion == 0) && (Type == gcvSURF_VERTEX))
+        {
+            gcmkONERROR(_AdjustIndex(
+                Mmu,
+                index,
+                PageCount,
+                gcdVERTEX_START / gcmSIZEOF(gctUINT32),
+                &index
+                ));
+        }
+
         /* Walk the heap list. */
-        for (index = Mmu->heapList; !gotIt && (index < Mmu->pageTableEntries);)
+        for (; !gotIt && (index < Mmu->pageTableEntries);)
         {
             /* Check the node type. */
             switch (gcmENTRY_TYPE(_ReadPageEntry(&pageTable[index])))
@@ -1422,6 +1521,19 @@ gckMMU_AllocatePages(
     OUT gctPOINTER * PageTable,
     OUT gctUINT32 * Address
     )
+{
+    return gckMMU_AllocatePagesEx(
+                Mmu, PageCount, gcvSURF_UNKNOWN, PageTable, Address);
+}
+
+gceSTATUS
+gckMMU_AllocatePagesEx(
+    IN gckMMU Mmu,
+    IN gctSIZE_T PageCount,
+    IN gceSURF_TYPE Type,
+    OUT gctPOINTER * PageTable,
+    OUT gctUINT32 * Address
+    )
 {
 #if gcdMIRROR_PAGETABLE
     gceSTATUS status;
@@ -1440,7 +1552,7 @@ gckMMU_AllocatePages(
     {
         if (Mmu == mirrorPageTable->mmus[i])
         {
-            gcmkONERROR(_AllocatePages(Mmu, PageCount, PageTable, Address));
+            gcmkONERROR(_AllocatePages(Mmu, PageCount, Type, PageTable, Address));
             allocated = gcvTRUE;
         }
     }
@@ -1452,7 +1564,7 @@ gckMMU_AllocatePages(
 
         if (Mmu != mmu)
         {
-            gcmkONERROR(_AllocatePages(mmu, PageCount, &pageTable, &address));
+            gcmkONERROR(_AllocatePages(mmu, PageCount, Type, &pageTable, &address));
             gcmkASSERT(address == *Address);
         }
     }
@@ -1478,7 +1590,7 @@ OnError:
 
     return status;
 #else
-    return _AllocatePages(Mmu, PageCount, PageTable, Address);
+    return _AllocatePages(Mmu, PageCount, Type, PageTable, Address);
 #endif
 }
 
index 99b6bd12c77c4b6ba76dbf11cb6ea4ac187fd443..39290c9e45d9e25b96e84167f580e9f66457f6e0 100644 (file)
@@ -1818,8 +1818,9 @@ gckVIDMEM_Lock(
                 {
                     /* Allocate pages inside the MMU. */
                     gcmkONERROR(
-                        gckMMU_AllocatePages(Kernel->mmu,
+                        gckMMU_AllocatePagesEx(Kernel->mmu,
                                              Node->Virtual.pageCount,
+                                             Node->Virtual.type,
                                              &Node->Virtual.pageTables[Kernel->core],
                                              &Node->Virtual.addresses[Kernel->core]));
                 }
index 7312cc24d598ea6fda45decba6f03d9b9e31198c..63d5dad3a75abcfd5e147f9ae5adada6df8b5001 100644 (file)
@@ -2562,6 +2562,15 @@ gckMMU_AllocatePages(
     OUT gctUINT32 * Address
     );
 
+gceSTATUS
+gckMMU_AllocatePagesEx(
+    IN gckMMU Mmu,
+    IN gctSIZE_T PageCount,
+    IN gceSURF_TYPE Type,
+    OUT gctPOINTER * PageTable,
+    OUT gctUINT32 * Address
+    );
+
 /* Remove a page table from the MMU. */
 gceSTATUS
 gckMMU_FreePages(
index 8e3c2f89a8a295e554d9d954652049db447b498d..31422cee56afe6e7c4ba6b79ad7c2c304c2438e2 100644 (file)
@@ -166,6 +166,7 @@ typedef enum _gceFEATURE
        gcvFEATURE_LINEAR_RENDER_TARGET,
     gcvFEATURE_BUG_FIXES8,
     gcvFEATURE_HALTI2,
+    gcvFEATURE_MMU,
 }
 gceFEATURE;