/* Push a new buffer object onto the list */ static void push_object(struct kgsl_device *device, int type, phys_addr_t ptbase, uint32_t gpuaddr, int dwords) { int index; void *ptr; struct kgsl_mem_entry *entry = NULL; /* * Sometimes IBs can be reused in the same dump. Because we parse from * oldest to newest, if we come across an IB that has already been used, * assume that it has been reused and update the list with the newest * size. */ for (index = 0; index < objbufptr; index++) { if (objbuf[index].gpuaddr == gpuaddr && objbuf[index].ptbase == ptbase) { objbuf[index].dwords = dwords; return; } } if (objbufptr == SNAPSHOT_OBJ_BUFSIZE) { KGSL_DRV_ERR(device, "snapshot: too many snapshot objects\n"); return; } /* * adreno_convertaddr verifies that the IB size is valid - at least in * the context of it being smaller then the allocated memory space */ ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2, &entry); if (ptr == NULL) { KGSL_DRV_ERR(device, "snapshot: Can't find GPU address for %x\n", gpuaddr); return; } /* Put it on the list of things to parse */ objbuf[objbufptr].type = type; objbuf[objbufptr].gpuaddr = gpuaddr; objbuf[objbufptr].ptbase = ptbase; objbuf[objbufptr].dwords = dwords; objbuf[objbufptr].entry = entry; objbuf[objbufptr++].ptr = ptr; }
static ssize_t kgsl_ib_dump_read( struct file *file, char __user *buff, size_t buff_count, loff_t *ppos) { int i, count = kgsl_ib_size, remaining, pos = 0, tot = 0, ss; struct kgsl_device *device = file->private_data; const int rowc = 32; unsigned int pt_base; uint8_t *base_addr; char linebuf[80]; if (!ppos || !device || !kgsl_ib_base) return 0; kgsl_regread(device, MH_MMU_PT_BASE, &pt_base); base_addr = adreno_convertaddr(device, pt_base, kgsl_ib_base, kgsl_ib_size*sizeof(uint32_t)); if (!base_addr) return 0; pr_info("%s ppos=%ld, buff_count=%d, count=%d\n", __func__, (long)*ppos, buff_count, count); ss = snprintf(linebuf, sizeof(linebuf), "IB: base=%08x(%08x" "), size=%d\n", kgsl_ib_base, (uint32_t)base_addr, kgsl_ib_size); if (*ppos == 0) { if (copy_to_user(buff, linebuf, ss+1)) return -EFAULT; tot += ss; buff += ss; *ppos += ss; } pos += ss; remaining = count; for (i = 0; i < count; i += rowc) { int linec = min(remaining, rowc); remaining -= rowc; ss = kgsl_hex_dump("IB: %05x: ", i, base_addr, rowc, linec, buff); if (ss < 0) return ss; if (pos >= *ppos) { if (tot+ss >= buff_count) { ss = copy_to_user(buff, "", 1); return tot; } tot += ss; buff += ss; *ppos += ss; } pos += ss; base_addr += linec; } return tot; }