xref: /OK3568_Linux_fs/kernel/drivers/soc/rockchip/rk_cma_procfs.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * CMA ProcFS Interface
4  *
5  * Copyright (C) 2022 Rockchip Electronics Co. Ltd.
6  */
7 
8 #include <linux/cma.h>
9 #include <linux/module.h>
10 #include <linux/proc_fs.h>
11 #include <linux/seq_file.h>
12 #include <linux/slab.h>
13 
14 #include "../../../mm/cma.h"
15 
cma_procfs_format_array(char * buf,size_t bufsize,u32 * array,int array_size)16 static void cma_procfs_format_array(char *buf, size_t bufsize, u32 *array, int array_size)
17 {
18 	int i = 0;
19 
20 	while (--array_size >= 0) {
21 		size_t len;
22 		char term = (array_size && (++i % 8)) ? ' ' : '\n';
23 
24 		len = snprintf(buf, bufsize, "%08X%c", *array++, term);
25 		buf += len;
26 		bufsize -= len;
27 	}
28 }
29 
cma_procfs_show_bitmap(struct seq_file * s,struct cma * cma)30 static void cma_procfs_show_bitmap(struct seq_file *s, struct cma *cma)
31 {
32 	int elements = DIV_ROUND_UP(cma_bitmap_maxno(cma), BITS_PER_BYTE * sizeof(u32));
33 	int size = elements * 9;
34 	u32 *array = (u32 *)cma->bitmap;
35 	char *buf;
36 
37 	buf = kmalloc(size + 1, GFP_KERNEL);
38 	if (!buf)
39 		return;
40 
41 	buf[size] = 0;
42 
43 	cma_procfs_format_array(buf, size + 1, array, elements);
44 	seq_printf(s, "%s", buf);
45 	kfree(buf);
46 }
47 
cma_procfs_used_get(struct cma * cma)48 static u64 cma_procfs_used_get(struct cma *cma)
49 {
50 	unsigned long used;
51 
52 	mutex_lock(&cma->lock);
53 	used = bitmap_weight(cma->bitmap, (int)cma_bitmap_maxno(cma));
54 	mutex_unlock(&cma->lock);
55 
56 	return (u64)used << cma->order_per_bit;
57 }
58 
cma_procfs_show(struct seq_file * s,void * private)59 static int cma_procfs_show(struct seq_file *s, void *private)
60 {
61 	struct cma *cma = s->private;
62 	u64 used = cma_procfs_used_get(cma);
63 
64 	seq_printf(s, "Total: %lu KiB\n", cma->count << (PAGE_SHIFT - 10));
65 	seq_printf(s, " Used: %llu KiB\n\n", used << (PAGE_SHIFT - 10));
66 
67 	cma_procfs_show_bitmap(s, cma);
68 
69 	return 0;
70 }
71 
cma_procfs_add_one(struct cma * cma,void * data)72 static int cma_procfs_add_one(struct cma *cma, void *data)
73 {
74 	struct proc_dir_entry *root = data;
75 
76 	proc_create_single_data(cma->name, 0, root, cma_procfs_show, cma);
77 
78 	return 0;
79 }
80 
rk_cma_procfs_init(void)81 static int rk_cma_procfs_init(void)
82 {
83 	struct proc_dir_entry *root = proc_mkdir("rk_cma", NULL);
84 
85 	return cma_for_each_area(cma_procfs_add_one, (void *)root);
86 }
87 late_initcall_sync(rk_cma_procfs_init);
88 
89 MODULE_LICENSE("GPL");
90 MODULE_AUTHOR("Jianqun Xu <jay.xu@rock-chips.com>");
91 MODULE_DESCRIPTION("ROCKCHIP CMA PROCFS Driver");
92 MODULE_ALIAS("platform:rk-cma");
93