gpu: pvr: get rid of unnecessary hash lookups for the proc object
[sgx.git] / pvr / sgxinit.c
index c551039..6170038 100644 (file)
@@ -47,7 +47,7 @@
 #include "resman.h"
 #include "bridged_support.h"
 
-#include "pdump_km.h"
+#include "pvr_pdump.h"
 #include "ra.h"
 #include "mmu.h"
 #include "mm.h"
 #include "pvrversion.h"
 #include "sgx_options.h"
 
+#ifdef CONFIG_DEBUG_FS
+#include "pvr_debugfs.h"
+#endif
+
 static IMG_BOOL SGX_ISRHandler(void *pvData);
 
 static u32 gui32EventStatusServicesByISR;
@@ -345,6 +349,8 @@ static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
 
        hKernelDevMemContext = BM_CreateContext(psDeviceNode, &sPDDevPAddr,
                                                NULL, NULL);
+       if (!hKernelDevMemContext)
+               goto err1;
 
        psDevInfo->sKernelPDDevPAddr = sPDDevPAddr;
 
@@ -360,6 +366,9 @@ static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
                                    BM_CreateHeap(hKernelDevMemContext,
                                                  &psDeviceMemoryHeap[i]);
 
+                               if (!hDevMemHeap)
+                                       goto err2;
+
                                psDeviceMemoryHeap[i].hDevMemHeap = hDevMemHeap;
                                break;
                        }
@@ -370,10 +379,28 @@ static enum PVRSRV_ERROR DevInitSGXPart1(void *pvDeviceNode)
        if (eError != PVRSRV_OK) {
                PVR_DPF(PVR_DBG_ERROR,
                         "DevInitSGX : Failed to alloc memory for BIF reset");
-               return PVRSRV_ERROR_GENERIC;
+               goto err2;
        }
 
        return PVRSRV_OK;
+err2:
+       while (i) {
+               int type;
+
+               i--;
+               type = psDeviceMemoryHeap[i].DevMemHeapType;
+               if (type != DEVICE_MEMORY_HEAP_KERNEL &&
+                   type != DEVICE_MEMORY_HEAP_SHARED &&
+                   type != DEVICE_MEMORY_HEAP_SHARED_EXPORTED)
+                       continue;
+               BM_DestroyHeap(psDeviceMemoryHeap[i].hDevMemHeap);
+       }
+       BM_DestroyContext(hKernelDevMemContext);
+err1:
+       OSFreeMem(PVRSRV_OS_NON_PAGEABLE_HEAP,
+                 sizeof(struct PVRSRV_SGXDEV_INFO), psDevInfo, NULL);
+
+       return PVRSRV_ERROR_GENERIC;
 }
 
 enum PVRSRV_ERROR SGXGetInfoForSrvinitKM(void *hDevHandle,
@@ -592,68 +619,6 @@ static enum PVRSRV_ERROR DevDeInitSGX(void *pvDeviceNode)
        return PVRSRV_OK;
 }
 
-#if defined(PVRSRV_USSE_EDM_STATUS_DEBUG) || defined(CONFIG_DEBUG_FS)
-
-static size_t __print_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *dst,
-                               size_t dst_len)
-{
-       u32 *buf_start;
-       u32 *buf_end;
-       u32 *buf;
-       size_t p = 0;
-       size_t wr_ofs;
-       int i;
-
-#define _PR(fmt, ...) do {                                                \
-       if (dst)                                                           \
-               p += snprintf(dst + p, dst_len - p, fmt, ## __VA_ARGS__);  \
-       else                                                               \
-               printk(KERN_DEBUG fmt, ## __VA_ARGS__);                    \
-} while (0)
-
-       if (!sdev->psKernelEDMStatusBufferMemInfo)
-               return 0;
-
-       buf = sdev->psKernelEDMStatusBufferMemInfo->pvLinAddrKM;
-
-       _PR("Last SGX microkernel status code: 0x%x\n", *buf);
-       buf++;
-       wr_ofs = *buf;
-       buf++;
-
-       buf_start = buf;
-       buf_end = buf + SGXMK_TRACE_BUFFER_SIZE * 4;
-
-       buf += wr_ofs * 4;
-
-       /* Dump the status values */
-       for (i = 0; i < SGXMK_TRACE_BUFFER_SIZE; i++) {
-               _PR("%3d %08X %08X %08X %08X\n",
-                   i, buf[2], buf[3], buf[1], buf[0]);
-               buf += 4;
-               if (buf >= buf_end)
-                       buf = buf_start;
-       }
-
-       return p > dst_len ? dst_len : p;
-#undef _PR
-}
-
-size_t snprint_edm_trace(struct PVRSRV_SGXDEV_INFO *sdev, char *buf,
-                        size_t buf_size)
-{
-       return __print_edm_trace(sdev, buf, buf_size);
-}
-
-#endif
-
-static void dump_edm(struct PVRSRV_SGXDEV_INFO *sdev)
-{
-#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
-       __print_edm_trace(sdev, NULL, 0);
-#endif
-}
-
 static struct PVRSRV_PER_PROCESS_DATA *find_cur_proc_data(
                                        struct PVRSRV_DEVICE_NODE *dev)
 {
@@ -674,25 +639,22 @@ static struct PVRSRV_PER_PROCESS_DATA *find_cur_proc_data(
        return proc_data;
 }
 
-static void dump_process_info(struct PVRSRV_DEVICE_NODE *dev)
+static void pr_err_process_info(struct PVRSRV_PER_PROCESS_DATA *proc)
 {
-       struct PVRSRV_PER_PROCESS_DATA *proc;
+       struct task_struct *tsk;
+       int pid;
 
-       proc = find_cur_proc_data(dev);
-
-       if (proc) {
-               struct task_struct *tsk;
-               int pid;
+       if (!proc)
+               return;
 
-               pid = proc->ui32PID;
-               rcu_read_lock();
-               tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
-               pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
-               rcu_read_unlock();
-       }
+       pid = proc->ui32PID;
+       rcu_read_lock();
+       tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
+       pr_err("PID = %d, process name = %s\n", pid, tsk->comm);
+       rcu_read_unlock();
 }
 
-static void dump_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
+static void pr_err_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
 {
        pr_err("EVENT_STATUS =     0x%08X\n"
                "EVENT_STATUS2 =    0x%08X\n"
@@ -710,244 +672,16 @@ static void dump_sgx_registers(struct PVRSRV_SGXDEV_INFO *psDevInfo)
                readl(psDevInfo->pvRegsBaseKM + EUR_CR_CLKGATECTL));
 }
 
-#define BUF_DESC_CORRUPT       (1 << 31)
-
-static void add_uniq_items(struct render_state_buf_list *dst,
-                          const struct render_state_buf_list *src)
-{
-       int i;
-
-       for (i = 0; i < src->cnt; i++) {
-               const struct render_state_buf_info *sbinf = &src->info[i];
-               int j;
-
-               for (j = 0; j < dst->cnt; j++) {
-                       if (sbinf->buf_id == dst->info[j].buf_id) {
-                               if (memcmp(sbinf, &dst->info[j], sizeof(sbinf)))
-                                       dst->info[j].type |= BUF_DESC_CORRUPT;
-                               break;
-                       }
-               }
-               if (j == dst->cnt) {
-                       /* Bound for cnt is guaranteed by the caller */
-                       dst->info[dst->cnt] = *sbinf;
-                       dst->cnt++;
-               }
-       }
-}
-
-static struct render_state_buf_list *create_merged_uniq_list(
-               struct render_state_buf_list **bl_set, int set_size)
-{
-       int i;
-       struct render_state_buf_list *dbl;
-       size_t size;
-
-       /*
-        * Create a buf list big enough to contain all elements from each
-        * list in bl_set.
-        */
-       size = offsetof(struct render_state_buf_list, info[0]);
-       for (i = 0; i < set_size; i++) {
-               if (!bl_set[i])
-                       continue;
-               size += bl_set[i]->cnt * sizeof(bl_set[i]->info[0]);
-       }
-       if (!size)
-               return NULL;
-       dbl = kmalloc(size, GFP_KERNEL);
-       if (!dbl)
-               return NULL;
-
-       dbl->cnt = 0;
-       for (i = 0; i < set_size; i++) {
-               if (bl_set[i])
-                       add_uniq_items(dbl, bl_set[i]);
-       }
-
-       return dbl;
-}
-
-static void *vmap_buf(struct PVRSRV_PER_PROCESS_DATA *proc,
-                       u32 handle, off_t offset, size_t size)
-{
-       struct PVRSRV_KERNEL_MEM_INFO *minfo;
-       struct LinuxMemArea *mem_area;
-       enum PVRSRV_ERROR err;
-       unsigned start_ofs;
-       unsigned end_ofs;
-       int pg_cnt;
-       struct page **pages;
-       void *map;
-       int i;
-
-       if (offset & PAGE_MASK)
-               return NULL;
-
-       err = PVRSRVLookupHandle(proc->psHandleBase, (void **)&minfo,
-                               (void *)handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
-       if (err != PVRSRV_OK)
-               return NULL;
-       if (minfo->pvLinAddrKM)
-               return minfo->pvLinAddrKM;
-
-       err = PVRSRVLookupOSMemHandle(proc->psHandleBase, (void *)&mem_area,
-                                       (void *)handle);
-       if (err != PVRSRV_OK)
-               return NULL;
-
-       start_ofs = offset & PAGE_MASK;
-       end_ofs = PAGE_ALIGN(offset + size);
-       pg_cnt = (end_ofs - start_ofs) >> PAGE_SHIFT;
-       pages = kmalloc(pg_cnt * sizeof(pages[0]), GFP_KERNEL);
-       if (!pages)
-               return NULL;
-       for (i = 0; i < pg_cnt; i++) {
-               unsigned pfn;
-
-               pfn = LinuxMemAreaToCpuPFN(mem_area, start_ofs);
-               if (!pfn_valid(pfn))
-                       goto err;
-               pages[i] = pfn_to_page(pfn);
-               start_ofs += PAGE_SIZE;
-       }
-       map = vmap(pages, pg_cnt, VM_MAP, PAGE_KERNEL);
-       map += offset;
-err:
-       kfree(pages);
-
-       return map;
-}
-
-static void vunmap_buf(struct PVRSRV_PER_PROCESS_DATA *proc,
-                       u32 handle, void *map)
-{
-       struct PVRSRV_KERNEL_MEM_INFO *minfo;
-       enum PVRSRV_ERROR err;
-
-       err = PVRSRVLookupHandle(proc->psHandleBase, (void **)&minfo,
-                               (void *)handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
-       if (err != PVRSRV_OK)
-               return;
-       if (minfo->pvLinAddrKM)
-               return;
-       vunmap((void *)(((unsigned long)map) & PAGE_MASK));
-}
-
-static void dump_buf(void *start, size_t size, u32 type)
-{
-       unsigned addr = 0;
-       char *corr = "";
-
-       if (type & BUF_DESC_CORRUPT) {
-               type &= ~BUF_DESC_CORRUPT;
-               corr = "(corrupt)";
-       }
-       printk(KERN_DEBUG "type %d%s size %d\n", type, corr, size);
-       while (addr < size) {
-               if (!(addr % 16)) {
-                       if (addr)
-                               printk("\n");
-                       printk(KERN_DEBUG "%08x ", addr);
-               }
-               printk("%08x ", *(u32 *)(start + addr));
-               addr += 4;
-       }
-       if (addr)
-               printk("\n");
-}
-
-static struct render_state_buf_list *get_state_buf_list(
-                       struct PVRSRV_PER_PROCESS_DATA *proc,
-                       u32 handle, off_t offset)
-{
-       struct PVRSRV_KERNEL_MEM_INFO *container;
-       struct render_state_buf_list *buf;
-       enum PVRSRV_ERROR err;
-
-       err = PVRSRVLookupHandle(proc->psHandleBase, (void **)&container,
-                               (void *)handle, PVRSRV_HANDLE_TYPE_MEM_INFO);
-       if (err != PVRSRV_OK)
-               return NULL;
-       if (!container->pvLinAddrKM)
-               return NULL;
-       if (offset + sizeof(*buf) > container->ui32AllocSize)
-               return NULL;
-
-       buf = container->pvLinAddrKM + offset;
-
-       if (buf->cnt > ARRAY_SIZE(buf->info))
-               return NULL;
-
-       return buf;
-}
-
-static void dump_state_buf_list(struct PVRSRV_PER_PROCESS_DATA *proc,
-                               struct render_state_buf_list *bl)
-{
-       int i;
-
-       if (!bl->cnt)
-               return;
-
-       printk(KERN_DEBUG "Dumping %d render state buffers\n", bl->cnt);
-       for (i = 0; i < bl->cnt; i++) {
-               struct render_state_buf_info *binfo;
-               void *map;
-
-               binfo = &bl->info[i];
-
-               map = vmap_buf(proc, binfo->buf_id, binfo->offset, binfo->size);
-               if (!map)
-                       continue;
-               dump_buf(map, binfo->size, binfo->type);
-
-               vunmap_buf(proc, binfo->buf_id, map);
-       }
-}
-
-static void dump_sgx_state_bufs(struct PVRSRV_DEVICE_NODE *dev_node)
-{
-       struct PVRSRV_SGXDEV_INFO *dev_info = dev_node->pvDevice;
-       struct SGXMKIF_HOST_CTL __iomem *hctl = dev_info->psSGXHostCtl;
-       struct PVRSRV_PER_PROCESS_DATA *proc;
-       struct render_state_buf_list *bl_set[2] = { NULL };
-       struct render_state_buf_list *mbl;
-       u32 handle_ta;
-       u32 handle_3d;
-
-       proc = find_cur_proc_data(dev_node);
-       if (!proc)
-               return;
-
-       handle_ta = readl(&hctl->render_state_buf_ta_handle);
-       handle_3d = readl(&hctl->render_state_buf_3d_handle);
-       bl_set[0] = get_state_buf_list(proc, handle_ta,
-                                       dev_info->state_buf_ofs);
-       /*
-        * The two buf list can be the same if the TA and 3D phases used the
-        * same context at the time of the HWrec. In this case just ignore
-        * one of them.
-        */
-       if (handle_ta != handle_3d)
-               bl_set[1] = get_state_buf_list(proc, handle_3d,
-                                       dev_info->state_buf_ofs);
-       mbl = create_merged_uniq_list(bl_set, ARRAY_SIZE(bl_set));
-       if (!mbl)
-               return;
-
-       dump_state_buf_list(proc, mbl);
-       kfree(mbl);
-}
-
 /* Should be called with pvr_lock held */
-void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode)
+void
+HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode, const char *caller)
 {
        enum PVRSRV_ERROR eError;
        struct PVRSRV_SGXDEV_INFO *psDevInfo =
            (struct PVRSRV_SGXDEV_INFO *)psDeviceNode->pvDevice;
        struct SGXMKIF_HOST_CTL __iomem *psSGXHostCtl =
                                        psDevInfo->psSGXHostCtl;
+       struct PVRSRV_PER_PROCESS_DATA *proc;
        u32 l;
        int max_retries = 10;
 
@@ -957,12 +691,19 @@ void HWRecoveryResetSGX(struct PVRSRV_DEVICE_NODE *psDeviceNode)
        l |= PVRSRV_USSE_EDM_INTERRUPT_HWR;
        writel(l, &psSGXHostCtl->ui32InterruptClearFlags);
 
-       pr_err("%s: SGX Hardware Recovery triggered\n", __func__);
+       pr_err("SGX Hardware Recovery triggered (from %s)\n", caller);
 
-       dump_process_info(psDeviceNode);
-       dump_sgx_registers(psDevInfo);
-       dump_edm(psDevInfo);
-       dump_sgx_state_bufs(psDeviceNode);
+       proc = find_cur_proc_data(psDeviceNode);
+
+       pr_err_process_info(proc);
+       pr_err_sgx_registers(psDevInfo);
+#ifdef PVRSRV_USSE_EDM_STATUS_DEBUG
+       edm_trace_print(psDevInfo, NULL, 0);
+#endif
+
+#ifdef CONFIG_DEBUG_FS
+       pvr_hwrec_dump(proc, psDevInfo);
+#endif
 
        PDUMPSUSPEND();
 
@@ -1061,7 +802,7 @@ static void SGXOSTimer(struct work_struct *work)
                l++;
                writel(l, &psSGXHostCtl->ui32HostDetectedLockups);
 
-               HWRecoveryResetSGX(psDeviceNode);
+               HWRecoveryResetSGX(psDeviceNode, __func__);
                pvr_dev_unlock();
        }
 
@@ -1199,7 +940,7 @@ static void SGX_MISRHandler(void *pvData)
 
        if ((l1 & PVRSRV_USSE_EDM_INTERRUPT_HWR) &&
            !(l2 & PVRSRV_USSE_EDM_INTERRUPT_HWR))
-               HWRecoveryResetSGX(psDeviceNode);
+               HWRecoveryResetSGX(psDeviceNode, __func__);
 
        if (psDeviceNode->bReProcessDeviceCommandComplete)
                SGXScheduleProcessQueues(psDeviceNode);