msm: kgsl: create sysfs entries to expose memory usage
Added sysfs entries to show kgsl memory usage statistics. gpumem_mapped: kgsl memory mapped in the process address space. gpumem_unmapped: kgsl allocated memory but not mapped in process. imported_mem: graphics memory not allocated by the kgsl. Below is the sysfs path for new entries: /sys/class/kgsl/kgsl/proc/<pid>/ Change-Id: I08c2014d28dc0ca1e2b54ebf966d00143b303b54 Signed-off-by: Amit Kushwaha <kushwaha@codeaurora.org>
This commit is contained in:
parent
2103804389
commit
015a6c37e1
3 changed files with 87 additions and 1 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue