Loading drivers/gpu/msm/kgsl_device.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading drivers/gpu/msm/kgsl_sharedmem.c +115 −31 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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), Loading @@ -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); } Loading Loading @@ -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, Loading Loading @@ -790,41 +896,19 @@ 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; for (i = 0; i < ARRAY_SIZE(memtypes); i++) { if (memtypes[i].type == type) { strlcpy(name, memtypes[i].attr.name, name_size); return; } } 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); } Loading Loading
drivers/gpu/msm/kgsl_device.h +1 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
drivers/gpu/msm/kgsl_sharedmem.c +115 −31 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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), Loading @@ -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); } Loading Loading @@ -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, Loading Loading @@ -790,41 +896,19 @@ 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; for (i = 0; i < ARRAY_SIZE(memtypes); i++) { if (memtypes[i].type == type) { strlcpy(name, memtypes[i].attr.name, name_size); return; } } 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); } Loading