diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 91e486cfa47e..0c4a1266efae 100755 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -459,6 +459,10 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry) type = kgsl_memdesc_usermem_type(&entry->memdesc); entry->priv->stats[type].cur -= entry->memdesc.size; + + if (type != KGSL_MEM_ENTRY_ION) + entry->priv->gpumem_mapped -= entry->memdesc.mapsize; + spin_unlock(&entry->priv->mem_lock); kgsl_mmu_put_gpuaddr(&entry->memdesc); @@ -4237,13 +4241,18 @@ static int kgsl_gpumem_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) { struct kgsl_mem_entry *entry = vma->vm_private_data; + int ret; if (!entry) return VM_FAULT_SIGBUS; if (!entry->memdesc.ops || !entry->memdesc.ops->vmfault) return VM_FAULT_SIGBUS; - return entry->memdesc.ops->vmfault(&entry->memdesc, vma, vmf); + ret = entry->memdesc.ops->vmfault(&entry->memdesc, vma, vmf); + if ((ret == 0) || (ret == VM_FAULT_NOPAGE)) + entry->priv->gpumem_mapped += PAGE_SIZE; + + return ret; } static void diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h index 0ab6041b3bbd..bfd99cde55fb 100644 --- a/drivers/gpu/msm/kgsl_device.h +++ b/drivers/gpu/msm/kgsl_device.h @@ -420,6 +420,7 @@ struct kgsl_context { * @kobj: Pointer to a kobj for the sysfs directory for this process * @debug_root: Pointer to the debugfs root for this process * @stats: Memory allocation statistics for this process + * @gpumem_mapped: KGSL memory mapped in the process address space * @syncsource_idr: sync sources created by this process * @syncsource_lock: Spinlock to protect the syncsource idr * @fd_count: Counter for the number of FDs for this process @@ -441,6 +442,7 @@ struct kgsl_process_private { uint64_t cur; uint64_t max; } stats[KGSL_MEM_ENTRY_MAX]; + uint64_t gpumem_mapped; struct idr syncsource_idr; spinlock_t syncsource_lock; int fd_count; diff --git a/drivers/gpu/msm/kgsl_sharedmem.c b/drivers/gpu/msm/kgsl_sharedmem.c index 4c54553e9977..fa9b66566004 100644 --- a/drivers/gpu/msm/kgsl_sharedmem.c +++ b/drivers/gpu/msm/kgsl_sharedmem.c @@ -98,6 +98,75 @@ struct mem_entry_stats { static void kgsl_cma_unlock_secure(struct kgsl_memdesc *memdesc); +static ssize_t +imported_mem_show(struct kgsl_process_private *priv, + int type, char *buf) +{ + struct kgsl_mem_entry *entry; + uint64_t imported_mem = 0; + int id = 0; + + spin_lock(&priv->mem_lock); + for (entry = idr_get_next(&priv->mem_idr, &id); entry; + id++, entry = idr_get_next(&priv->mem_idr, &id)) { + + int egl_surface_count = 0, egl_image_count = 0; + struct kgsl_memdesc *m; + + if (kgsl_mem_entry_get(entry) == 0) + continue; + spin_unlock(&priv->mem_lock); + + m = &entry->memdesc; + if (kgsl_memdesc_usermem_type(m) == KGSL_MEM_ENTRY_ION) { + kgsl_get_egl_counts(entry, &egl_surface_count, + &egl_image_count); + + if (kgsl_memdesc_get_memtype(m) == + KGSL_MEMTYPE_EGL_SURFACE) + imported_mem += m->size; + else if (egl_surface_count == 0) { + uint64_t size = m->size; + + do_div(size, (egl_image_count ? + egl_image_count : 1)); + imported_mem += size; + } + } + + kgsl_mem_entry_put(entry); + spin_lock(&priv->mem_lock); + } + spin_unlock(&priv->mem_lock); + + return scnprintf(buf, PAGE_SIZE, "%llu\n", imported_mem); +} + +static ssize_t +gpumem_mapped_show(struct kgsl_process_private *priv, + int type, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%llu\n", + priv->gpumem_mapped); +} + +static ssize_t +gpumem_unmapped_show(struct kgsl_process_private *priv, int type, char *buf) +{ + if (priv->gpumem_mapped > priv->stats[type].cur) + return -EIO; + + return scnprintf(buf, PAGE_SIZE, "%llu\n", + priv->stats[type].cur - priv->gpumem_mapped); +} + +static struct kgsl_mem_entry_attribute debug_memstats[] = { + __MEM_ENTRY_ATTR(0, imported_mem, imported_mem_show), + __MEM_ENTRY_ATTR(0, gpumem_mapped, gpumem_mapped_show), + __MEM_ENTRY_ATTR(KGSL_MEM_ENTRY_KERNEL, gpumem_unmapped, + gpumem_unmapped_show), +}; + /** * Show the current amount of memory allocated for the given memtype */ @@ -220,7 +289,13 @@ void kgsl_process_init_sysfs(struct kgsl_device *device, &mem_stats[i].max_attr.attr)) WARN(1, "Couldn't create sysfs file '%s'\n", mem_stats[i].max_attr.attr.name); + } + for (i = 0; i < ARRAY_SIZE(debug_memstats); i++) { + if (sysfs_create_file(&private->kobj, + &debug_memstats[i].attr)) + WARN(1, "Couldn't create sysfs file '%s'\n", + debug_memstats[i].attr.name); } }