xref: /OK3568_Linux_fs/kernel/mm/cma_debug_bitmap_hex.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * CMA DebugFS Interface
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright (c) 2015 Sasha Levin <sasha.levin@oracle.com>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 2022 Rockchip Electronics Co. Ltd.
8*4882a593Smuzhiyun  *
9*4882a593Smuzhiyun  */
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <linux/debugfs.h>
12*4882a593Smuzhiyun #include <linux/fs.h>
13*4882a593Smuzhiyun #include <linux/seq_file.h>
14*4882a593Smuzhiyun #include <linux/cma.h>
15*4882a593Smuzhiyun #include <linux/list.h>
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/slab.h>
18*4882a593Smuzhiyun #include <linux/mm_types.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include "cma.h"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static size_t
u32_format_array_hex(char * buf,size_t bufsize,u32 * array,int array_size)23*4882a593Smuzhiyun u32_format_array_hex(char *buf, size_t bufsize, u32 *array, int array_size)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	int i = 0;
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun 	while (--array_size >= 0) {
28*4882a593Smuzhiyun 		size_t len;
29*4882a593Smuzhiyun 		char term = (array_size && (++i % 8)) ? ' ' : '\n';
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun 		len = snprintf(buf, bufsize, "%08X%c", *array++, term);
32*4882a593Smuzhiyun 		buf += len;
33*4882a593Smuzhiyun 		bufsize -= len;
34*4882a593Smuzhiyun 	}
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	return 0;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
u32_array_open_hex(struct inode * inode,struct file * file)39*4882a593Smuzhiyun static int u32_array_open_hex(struct inode *inode, struct file *file)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	struct debugfs_u32_array *data = inode->i_private;
42*4882a593Smuzhiyun 	int size, elements = data->n_elements;
43*4882a593Smuzhiyun 	char *buf;
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	/*
46*4882a593Smuzhiyun 	 * Max size:
47*4882a593Smuzhiyun 	 *  - 8 digits + ' '/'\n' = 9 bytes per number
48*4882a593Smuzhiyun 	 *  - terminating NUL character
49*4882a593Smuzhiyun 	 */
50*4882a593Smuzhiyun 	size = elements * 9;
51*4882a593Smuzhiyun 	buf = kmalloc(size + 1, GFP_KERNEL);
52*4882a593Smuzhiyun 	if (!buf)
53*4882a593Smuzhiyun 		return -ENOMEM;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	buf[size] = 0;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	file->private_data = buf;
58*4882a593Smuzhiyun 	u32_format_array_hex(buf, size + 1, data->array, data->n_elements);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	return nonseekable_open(inode, file);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static ssize_t
u32_array_read(struct file * file,char __user * buf,size_t len,loff_t * ppos)64*4882a593Smuzhiyun u32_array_read(struct file *file, char __user *buf, size_t len, loff_t *ppos)
65*4882a593Smuzhiyun {
66*4882a593Smuzhiyun 	size_t size = strlen(file->private_data);
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return simple_read_from_buffer(buf, len, ppos,
69*4882a593Smuzhiyun 					file->private_data, size);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun 
u32_array_release(struct inode * inode,struct file * file)72*4882a593Smuzhiyun static int u32_array_release(struct inode *inode, struct file *file)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	kfree(file->private_data);
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	return 0;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun static const struct file_operations u32_array_hex_fops = {
80*4882a593Smuzhiyun 	.owner	 = THIS_MODULE,
81*4882a593Smuzhiyun 	.open	 = u32_array_open_hex,
82*4882a593Smuzhiyun 	.release = u32_array_release,
83*4882a593Smuzhiyun 	.read	 = u32_array_read,
84*4882a593Smuzhiyun 	.llseek  = no_llseek,
85*4882a593Smuzhiyun };
86*4882a593Smuzhiyun 
debugfs_create_u32_array_hex(const char * name,umode_t mode,struct dentry * parent,struct debugfs_u32_array * array)87*4882a593Smuzhiyun static void debugfs_create_u32_array_hex(const char *name, umode_t mode,
88*4882a593Smuzhiyun 				  struct dentry *parent,
89*4882a593Smuzhiyun 				  struct debugfs_u32_array *array)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun 	debugfs_create_file_unsafe(name, mode, parent, array, &u32_array_hex_fops);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
cma_debugfs_add_one(struct cma * cma,struct dentry * root_dentry)94*4882a593Smuzhiyun static int cma_debugfs_add_one(struct cma *cma, struct dentry *root_dentry)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct dentry *tmp;
97*4882a593Smuzhiyun 	char name[16];
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun 	scnprintf(name, sizeof(name), "cma-%s", cma->name);
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	tmp = debugfs_lookup(name, root_dentry);
102*4882a593Smuzhiyun 	if (!tmp)
103*4882a593Smuzhiyun 		return -EPROBE_DEFER;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	debugfs_create_u32_array_hex("bitmap_hex", 0444, tmp, &cma->dfs_bitmap);
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	return 0;
108*4882a593Smuzhiyun }
109*4882a593Smuzhiyun 
rk_cma_debugfs_init(void)110*4882a593Smuzhiyun static int __init rk_cma_debugfs_init(void)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun 	struct dentry *cma_debugfs_root;
113*4882a593Smuzhiyun 	int ret;
114*4882a593Smuzhiyun 	int i;
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	cma_debugfs_root = debugfs_lookup("cma", NULL);
117*4882a593Smuzhiyun 	if (!cma_debugfs_root)
118*4882a593Smuzhiyun 		return -EPROBE_DEFER;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	for (i = 0; i < cma_area_count; i++) {
121*4882a593Smuzhiyun 		ret = cma_debugfs_add_one(&cma_areas[i], cma_debugfs_root);
122*4882a593Smuzhiyun 		if (ret)
123*4882a593Smuzhiyun 			return ret;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 
126*4882a593Smuzhiyun 	return 0;
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun late_initcall(rk_cma_debugfs_init);
129