Merge "msm: kgsl: Expose memtype stats through sysfs"

This commit is contained in:
qctecmdr 2021-05-09 22:55:47 -07:00 • committed by Gerrit - the friendly Code Review server
commit 8336f3edcd
2 changed files with 116 additions and 31 deletions

View file

@ -448,6 +448,7 @@ struct kgsl_process_private {
struct kgsl_pagetable *pagetable;
struct list_head list;
struct kobject kobj;
struct kobject kobj_memtype;
struct dentry *debug_root;
struct {
atomic64_t cur;

View file

@ -24,6 +24,41 @@ static bool sharedmem_noretry_flag;
static DEFINE_MUTEX(kernel_map_global_lock);
#define MEMTYPE(_type, _name) { \
.type = _type, \
.attr = { .name = _name, .mode = 0444 } \
}
struct kgsl_memtype {
unsigned int type;
struct attribute attr;
};
static const struct kgsl_memtype memtypes[] = {
MEMTYPE(KGSL_MEMTYPE_OBJECTANY, "any(0)"),
MEMTYPE(KGSL_MEMTYPE_FRAMEBUFFER, "framebuffer"),
MEMTYPE(KGSL_MEMTYPE_RENDERBUFFER, "renderbuffer"),
MEMTYPE(KGSL_MEMTYPE_ARRAYBUFFER, "arraybuffer"),
MEMTYPE(KGSL_MEMTYPE_ELEMENTARRAYBUFFER, "elementarraybuffer"),
MEMTYPE(KGSL_MEMTYPE_VERTEXARRAYBUFFER, "vertexarraybuffer"),
MEMTYPE(KGSL_MEMTYPE_TEXTURE, "texture"),
MEMTYPE(KGSL_MEMTYPE_SURFACE, "surface"),
MEMTYPE(KGSL_MEMTYPE_EGL_SURFACE, "egl_surface"),
MEMTYPE(KGSL_MEMTYPE_GL, "gl"),
MEMTYPE(KGSL_MEMTYPE_CL, "cl"),
MEMTYPE(KGSL_MEMTYPE_CL_BUFFER_MAP, "cl_buffer_map"),
MEMTYPE(KGSL_MEMTYPE_CL_BUFFER_NOMAP, "cl_buffer_nomap"),
MEMTYPE(KGSL_MEMTYPE_CL_IMAGE_MAP, "cl_image_map"),
MEMTYPE(KGSL_MEMTYPE_CL_IMAGE_NOMAP, "cl_image_nomap"),
MEMTYPE(KGSL_MEMTYPE_CL_KERNEL_STACK, "cl_kernel_stack"),
MEMTYPE(KGSL_MEMTYPE_COMMAND, "command"),
MEMTYPE(KGSL_MEMTYPE_2D, "2d"),
MEMTYPE(KGSL_MEMTYPE_EGL_IMAGE, "egl_image"),
MEMTYPE(KGSL_MEMTYPE_EGL_SHADOW, "egl_shadow"),
MEMTYPE(KGSL_MEMTYPE_MULTISAMPLE, "egl_multisample"),
MEMTYPE(KGSL_MEMTYPE_KERNEL, "kernel"),
};
/* An attribute for showing per-process memory statistics */
struct kgsl_mem_entry_attribute {
struct attribute attr;
@ -183,6 +218,49 @@ static ssize_t mem_entry_sysfs_show(struct kobject *kobj,
return ret;
}
static ssize_t memtype_sysfs_show(struct kobject *kobj,
struct attribute *attr, char *buf)
{
struct kgsl_process_private *priv;
struct kgsl_memtype *memtype;
struct kgsl_mem_entry *entry;
u64 size = 0;
int id = 0;
/*
* kgsl_process_init_sysfs takes a refcount to the process_private,
* which is put when the kobj is released. This implies that priv will
* not be freed until this function completes, and no further locking
* is needed.
*/
priv = container_of(kobj, struct kgsl_process_private, kobj_memtype);
memtype = container_of(attr, struct kgsl_memtype, attr);
spin_lock(&priv->mem_lock);
for (entry = idr_get_next(&priv->mem_idr, &id); entry;
id++, entry = idr_get_next(&priv->mem_idr, &id)) {
struct kgsl_memdesc *memdesc;
unsigned int type;
if (kgsl_mem_entry_get(entry) == 0)
continue;
spin_unlock(&priv->mem_lock);
memdesc = &entry->memdesc;
type = MEMFLAGS(memdesc->flags, KGSL_MEMTYPE_MASK,
KGSL_MEMTYPE_SHIFT);
if (type == memtype->type)
size += memdesc->size;
kgsl_mem_entry_put(entry);
spin_lock(&priv->mem_lock);
}
spin_unlock(&priv->mem_lock);
return scnprintf(buf, PAGE_SIZE, "%llu\n", size);
}
static void mem_entry_release(struct kobject *kobj)
{
struct kgsl_process_private *priv;
@ -201,6 +279,14 @@ static struct kobj_type ktype_mem_entry = {
.release = &mem_entry_release,
};
static const struct sysfs_ops memtype_sysfs_ops = {
.show = memtype_sysfs_show,
};
static struct kobj_type ktype_memtype = {
.sysfs_ops = &memtype_sysfs_ops,
};
static struct mem_entry_stats mem_stats[] = {
MEM_ENTRY_STAT(KGSL_MEM_ENTRY_KERNEL, kernel),
MEM_ENTRY_STAT(KGSL_MEM_ENTRY_USER, user),
@ -220,6 +306,11 @@ kgsl_process_uninit_sysfs(struct kgsl_process_private *private)
&mem_stats[i].max_attr.attr);
}
for (i = 0; i < ARRAY_SIZE(memtypes); i++)
sysfs_remove_file(&private->kobj_memtype, &memtypes[i].attr);
kobject_put(&private->kobj_memtype);
kobject_put(&private->kobj);
}
@ -268,6 +359,21 @@ void kgsl_process_init_sysfs(struct kgsl_device *device,
WARN(1, "Couldn't create sysfs file '%s'\n",
debug_memstats[i].attr.name);
}
if (kobject_init_and_add(&private->kobj_memtype, &ktype_memtype,
&private->kobj, "memtype")) {
dev_err(device->dev,
"Unable to add memtype sysfs for process %d\n",
pid_nr(private->pid));
return;
}
for (i = 0; i < ARRAY_SIZE(memtypes); i++) {
if (sysfs_create_file(&private->kobj_memtype,
&memtypes[i].attr))
WARN(1, "Couldn't create sysfs file '%s'\n",
memtypes[i].attr.name);
}
}
static ssize_t memstat_show(struct device *dev,
@ -790,42 +896,20 @@ kgsl_sharedmem_writeq(const struct kgsl_memdesc *memdesc,
wmb();
}
static const char * const memtype_str[] = {
[KGSL_MEMTYPE_OBJECTANY] = "any(0)",
[KGSL_MEMTYPE_FRAMEBUFFER] = "framebuffer",
[KGSL_MEMTYPE_RENDERBUFFER] = "renderbuffer",
[KGSL_MEMTYPE_ARRAYBUFFER] = "arraybuffer",
[KGSL_MEMTYPE_ELEMENTARRAYBUFFER] = "elementarraybuffer",
[KGSL_MEMTYPE_VERTEXARRAYBUFFER] = "vertexarraybuffer",
[KGSL_MEMTYPE_TEXTURE] = "texture",
[KGSL_MEMTYPE_SURFACE] = "surface",
[KGSL_MEMTYPE_EGL_SURFACE] = "egl_surface",
[KGSL_MEMTYPE_GL] = "gl",
[KGSL_MEMTYPE_CL] = "cl",
[KGSL_MEMTYPE_CL_BUFFER_MAP] = "cl_buffer_map",
[KGSL_MEMTYPE_CL_BUFFER_NOMAP] = "cl_buffer_nomap",
[KGSL_MEMTYPE_CL_IMAGE_MAP] = "cl_image_map",
[KGSL_MEMTYPE_CL_IMAGE_NOMAP] = "cl_image_nomap",
[KGSL_MEMTYPE_CL_KERNEL_STACK] = "cl_kernel_stack",
[KGSL_MEMTYPE_COMMAND] = "command",
[KGSL_MEMTYPE_2D] = "2d",
[KGSL_MEMTYPE_EGL_IMAGE] = "egl_image",
[KGSL_MEMTYPE_EGL_SHADOW] = "egl_shadow",
[KGSL_MEMTYPE_MULTISAMPLE] = "egl_multisample",
/* KGSL_MEMTYPE_KERNEL handled below, to avoid huge array */
};
void kgsl_get_memory_usage(char *name, size_t name_size, uint64_t memflags)
{
unsigned int type = MEMFLAGS(memflags, KGSL_MEMTYPE_MASK,
KGSL_MEMTYPE_SHIFT);
int i;
if (type == KGSL_MEMTYPE_KERNEL)
strlcpy(name, "kernel", name_size);
else if (type < ARRAY_SIZE(memtype_str) && memtype_str[type] != NULL)
strlcpy(name, memtype_str[type], name_size);
else
snprintf(name, name_size, "VK/others(%3d)", type);
for (i = 0; i < ARRAY_SIZE(memtypes); i++) {
if (memtypes[i].type == type) {
strlcpy(name, memtypes[i].attr.name, name_size);
return;
}
}
snprintf(name, name_size, "VK/others(%3d)", type);
}
int kgsl_memdesc_sg_dma(struct kgsl_memdesc *memdesc,