Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 8336f3ed authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

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

parents 45a12290 76e3267c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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;
+115 −31
Original line number Diff line number Diff line
@@ -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,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);
}