ANDROID: dma-buf: heaps: Add a sysfs file to report total pool size.

In order to help with memory accounting, expose the total pool size of
all DMA-BUF heaps at /sys/kernel/dma_heap/total_pools_kb.

This information will be exposed as part of Android Bugreport[1].

[1]: https://android-review.googlesource.com/q/topic:%22b%252F167709539%22+(status:open%20OR%20status:merged)

Bug: 167709539
Change-Id: I6a1b52517e73103122690f6567f4f295db9ca1ad
Signed-off-by: Hridya Valsaraju <hridya@google.com>
This commit is contained in:
Hridya Valsaraju
2021-01-31 20:38:27 -08:00
parent 7f612dda44
commit 32fe36e04d
3 changed files with 72 additions and 3 deletions

View File

@@ -0,0 +1,7 @@
What: /sys/kernel/dma_heap/total_pools_kb
Date: Feb 2021
KernelVersion: 5.10
Contact: Hridya Valsaraju <hridya@google.com>,
Description:
The total_pools_kb file is read-only and specifies how much
memory in Kb is allocated to DMA-BUF heap pools.

View File

@@ -383,21 +383,81 @@ static char *dma_heap_devnode(struct device *dev, umode_t *mode)
return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev)); return kasprintf(GFP_KERNEL, "dma_heap/%s", dev_name(dev));
} }
static ssize_t total_pools_kb_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf)
{
struct dma_heap *heap;
u64 total_pool_size = 0;
mutex_lock(&heap_list_lock);
list_for_each_entry(heap, &heap_list, list) {
if (heap->ops->get_pool_size)
total_pool_size += heap->ops->get_pool_size(heap);
}
mutex_unlock(&heap_list_lock);
return sysfs_emit(buf, "%llu\n", total_pool_size / 1024);
}
static struct kobj_attribute total_pools_kb_attr =
__ATTR_RO(total_pools_kb);
static struct attribute *dma_heap_sysfs_attrs[] = {
&total_pools_kb_attr.attr,
NULL,
};
ATTRIBUTE_GROUPS(dma_heap_sysfs);
static struct kobject *dma_heap_kobject;
static int dma_heap_sysfs_setup(void)
{
int ret;
dma_heap_kobject = kobject_create_and_add("dma_heap", kernel_kobj);
if (!dma_heap_kobject)
return -ENOMEM;
ret = sysfs_create_groups(dma_heap_kobject, dma_heap_sysfs_groups);
if (ret) {
kobject_put(dma_heap_kobject);
return ret;
}
return 0;
}
static void dma_heap_sysfs_teardown(void)
{
kobject_put(dma_heap_kobject);
}
static int dma_heap_init(void) static int dma_heap_init(void)
{ {
int ret; int ret;
ret = alloc_chrdev_region(&dma_heap_devt, 0, NUM_HEAP_MINORS, DEVNAME); ret = dma_heap_sysfs_setup();
if (ret) if (ret)
return ret; return ret;
ret = alloc_chrdev_region(&dma_heap_devt, 0, NUM_HEAP_MINORS, DEVNAME);
if (ret)
goto err_chrdev;
dma_heap_class = class_create(THIS_MODULE, DEVNAME); dma_heap_class = class_create(THIS_MODULE, DEVNAME);
if (IS_ERR(dma_heap_class)) { if (IS_ERR(dma_heap_class)) {
unregister_chrdev_region(dma_heap_devt, NUM_HEAP_MINORS); ret = PTR_ERR(dma_heap_class);
return PTR_ERR(dma_heap_class); goto err_class;
} }
dma_heap_class->devnode = dma_heap_devnode; dma_heap_class->devnode = dma_heap_devnode;
return 0; return 0;
err_class:
unregister_chrdev_region(dma_heap_devt, NUM_HEAP_MINORS);
err_chrdev:
dma_heap_sysfs_teardown();
return ret;
} }
subsys_initcall(dma_heap_init); subsys_initcall(dma_heap_init);

View File

@@ -17,6 +17,7 @@ struct dma_heap;
/** /**
* struct dma_heap_ops - ops to operate on a given heap * struct dma_heap_ops - ops to operate on a given heap
* @allocate: allocate dmabuf and return struct dma_buf ptr * @allocate: allocate dmabuf and return struct dma_buf ptr
* @get_pool_size: if heap maintains memory pools, get pool size in bytes
* *
* allocate returns dmabuf on success, ERR_PTR(-errno) on error. * allocate returns dmabuf on success, ERR_PTR(-errno) on error.
*/ */
@@ -25,6 +26,7 @@ struct dma_heap_ops {
unsigned long len, unsigned long len,
unsigned long fd_flags, unsigned long fd_flags,
unsigned long heap_flags); unsigned long heap_flags);
long (*get_pool_size)(struct dma_heap *heap);
}; };
/** /**