xref: /wlan-driver/qca-wifi-host-cmn/qdf/linux/src/qdf_debugfs.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name  *
5*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
6*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
7*5113495bSYour Name  * above copyright notice and this permission notice appear in all
8*5113495bSYour Name  * copies.
9*5113495bSYour Name  *
10*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
18*5113495bSYour Name  */
19*5113495bSYour Name 
20*5113495bSYour Name /**
21*5113495bSYour Name  * DOC: qdf_debugfs
22*5113495bSYour Name  * This file provides QDF debug file system APIs
23*5113495bSYour Name  */
24*5113495bSYour Name 
25*5113495bSYour Name #include <qdf_debugfs.h>
26*5113495bSYour Name #include <i_qdf_debugfs.h>
27*5113495bSYour Name #include <qdf_mem.h>
28*5113495bSYour Name #include <qdf_trace.h>
29*5113495bSYour Name #include <qdf_module.h>
30*5113495bSYour Name 
31*5113495bSYour Name /* A private structure definition to qdf sequence */
32*5113495bSYour Name struct qdf_debugfs_seq_priv {
33*5113495bSYour Name 	bool stop;
34*5113495bSYour Name };
35*5113495bSYour Name 
36*5113495bSYour Name /* entry for root debugfs directory*/
37*5113495bSYour Name static qdf_dentry_t qdf_debugfs_root;
38*5113495bSYour Name 
qdf_debugfs_init(void)39*5113495bSYour Name QDF_STATUS qdf_debugfs_init(void)
40*5113495bSYour Name {
41*5113495bSYour Name 	qdf_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL);
42*5113495bSYour Name 
43*5113495bSYour Name 	if (!qdf_debugfs_root)
44*5113495bSYour Name 		return QDF_STATUS_E_FAILURE;
45*5113495bSYour Name 
46*5113495bSYour Name 	return QDF_STATUS_SUCCESS;
47*5113495bSYour Name }
48*5113495bSYour Name qdf_export_symbol(qdf_debugfs_init);
49*5113495bSYour Name 
qdf_debugfs_exit(void)50*5113495bSYour Name void qdf_debugfs_exit(void)
51*5113495bSYour Name {
52*5113495bSYour Name 	if (!qdf_debugfs_root)
53*5113495bSYour Name 		return;
54*5113495bSYour Name 
55*5113495bSYour Name 	debugfs_remove_recursive(qdf_debugfs_root);
56*5113495bSYour Name 	qdf_debugfs_root = NULL;
57*5113495bSYour Name }
58*5113495bSYour Name qdf_export_symbol(qdf_debugfs_exit);
59*5113495bSYour Name 
qdf_debugfs_get_root(void)60*5113495bSYour Name qdf_dentry_t qdf_debugfs_get_root(void)
61*5113495bSYour Name {
62*5113495bSYour Name 	return qdf_debugfs_root;
63*5113495bSYour Name }
64*5113495bSYour Name qdf_export_symbol(qdf_debugfs_get_root);
65*5113495bSYour Name 
qdf_debugfs_get_filemode(uint16_t mode)66*5113495bSYour Name umode_t qdf_debugfs_get_filemode(uint16_t mode)
67*5113495bSYour Name {
68*5113495bSYour Name 	umode_t ret = 0;
69*5113495bSYour Name 
70*5113495bSYour Name 	if (mode & QDF_FILE_USR_READ)
71*5113495bSYour Name 		ret |= 0400;
72*5113495bSYour Name 	if (mode & QDF_FILE_USR_WRITE)
73*5113495bSYour Name 		ret |= 0200;
74*5113495bSYour Name 
75*5113495bSYour Name 	if (mode & QDF_FILE_GRP_READ)
76*5113495bSYour Name 		ret |= 0040;
77*5113495bSYour Name 	if (mode & QDF_FILE_GRP_WRITE)
78*5113495bSYour Name 		ret |= 0020;
79*5113495bSYour Name 
80*5113495bSYour Name 	if (mode & QDF_FILE_OTH_READ)
81*5113495bSYour Name 		ret |= 0004;
82*5113495bSYour Name 	if (mode & QDF_FILE_OTH_WRITE)
83*5113495bSYour Name 		ret |= 0002;
84*5113495bSYour Name 
85*5113495bSYour Name 	return ret;
86*5113495bSYour Name }
87*5113495bSYour Name 
88*5113495bSYour Name /*
89*5113495bSYour Name  * ---------------------- Implementation note ---------------------------------
90*5113495bSYour Name  *
91*5113495bSYour Name  * A read in debugfs file triggers seq_read() which calls seq_read api. A
92*5113495bSYour Name  * sequence begins with the call of the function start(). If the return is a non
93*5113495bSYour Name  * NULL value, the function next() is called. This function is an iterator, the
94*5113495bSYour Name  * goal is to go though all the data. Each time next() is called, the function
95*5113495bSYour Name  * show() is also called. It writes data values in the buffer read by the user.
96*5113495bSYour Name  * The function next() is called until it returns NULL. The sequence ends when
97*5113495bSYour Name  * next() returns NULL, then the function stop() is called.
98*5113495bSYour Name  *
99*5113495bSYour Name  * NOTE: When a sequence is finished, another one starts. That means that
100*5113495bSYour Name  * at the end of function stop(), the function start() is called again. This
101*5113495bSYour Name  * loop finishes when the function start() returns NULL.
102*5113495bSYour Name  * ----------------------------------------------------------------------------
103*5113495bSYour Name  */
104*5113495bSYour Name 
105*5113495bSYour Name /* .seq_start() */
qdf_debugfs_seq_start(struct seq_file * seq,loff_t * pos)106*5113495bSYour Name static void *qdf_debugfs_seq_start(struct seq_file *seq, loff_t *pos)
107*5113495bSYour Name {
108*5113495bSYour Name 	struct qdf_debugfs_seq_priv *priv;
109*5113495bSYour Name 
110*5113495bSYour Name 	priv = qdf_mem_malloc(sizeof(*priv));
111*5113495bSYour Name 	if (!priv)
112*5113495bSYour Name 		return NULL;
113*5113495bSYour Name 
114*5113495bSYour Name 	priv->stop = false;
115*5113495bSYour Name 
116*5113495bSYour Name 	return priv;
117*5113495bSYour Name }
118*5113495bSYour Name 
119*5113495bSYour Name /* .seq_next() */
qdf_debugfs_seq_next(struct seq_file * seq,void * v,loff_t * pos)120*5113495bSYour Name static void *qdf_debugfs_seq_next(struct seq_file *seq, void *v, loff_t *pos)
121*5113495bSYour Name {
122*5113495bSYour Name 	struct qdf_debugfs_seq_priv *priv = v;
123*5113495bSYour Name 
124*5113495bSYour Name 	if (priv)
125*5113495bSYour Name 		++*pos;
126*5113495bSYour Name 
127*5113495bSYour Name 	if (priv && priv->stop) {
128*5113495bSYour Name 		qdf_mem_free(priv);
129*5113495bSYour Name 		priv = NULL;
130*5113495bSYour Name 	}
131*5113495bSYour Name 
132*5113495bSYour Name 	return priv;
133*5113495bSYour Name }
134*5113495bSYour Name 
135*5113495bSYour Name /* .seq_stop() */
qdf_debugfs_seq_stop(struct seq_file * seq,void * v)136*5113495bSYour Name static void qdf_debugfs_seq_stop(struct seq_file *seq, void *v)
137*5113495bSYour Name {
138*5113495bSYour Name 	qdf_mem_free(v);
139*5113495bSYour Name }
140*5113495bSYour Name 
141*5113495bSYour Name /* .seq_show() */
qdf_debugfs_seq_show(struct seq_file * seq,void * v)142*5113495bSYour Name static int qdf_debugfs_seq_show(struct seq_file *seq, void *v)
143*5113495bSYour Name {
144*5113495bSYour Name 	struct qdf_debugfs_seq_priv *priv = v;
145*5113495bSYour Name 	struct qdf_debugfs_fops *fops;
146*5113495bSYour Name 	QDF_STATUS status;
147*5113495bSYour Name 
148*5113495bSYour Name 	fops = seq->private;
149*5113495bSYour Name 
150*5113495bSYour Name 	if (fops && fops->show) {
151*5113495bSYour Name 		status = fops->show(seq, fops->priv);
152*5113495bSYour Name 
153*5113495bSYour Name 		if (priv && (status != QDF_STATUS_E_AGAIN))
154*5113495bSYour Name 			priv->stop = true;
155*5113495bSYour Name 	}
156*5113495bSYour Name 
157*5113495bSYour Name 	return 0;
158*5113495bSYour Name }
159*5113495bSYour Name 
qdf_debugfs_printf(qdf_debugfs_file_t file,const char * f,...)160*5113495bSYour Name void qdf_debugfs_printf(qdf_debugfs_file_t file, const char *f, ...)
161*5113495bSYour Name {
162*5113495bSYour Name 	va_list args;
163*5113495bSYour Name 
164*5113495bSYour Name 	va_start(args, f);
165*5113495bSYour Name 	seq_vprintf(file, f, args);
166*5113495bSYour Name 	va_end(args);
167*5113495bSYour Name }
168*5113495bSYour Name 
169*5113495bSYour Name qdf_export_symbol(qdf_debugfs_printf);
170*5113495bSYour Name 
171*5113495bSYour Name #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0))
172*5113495bSYour Name 
qdf_debugfs_hexdump(qdf_debugfs_file_t file,const uint8_t * buf,qdf_size_t len,int rowsize,int groupsize)173*5113495bSYour Name void qdf_debugfs_hexdump(qdf_debugfs_file_t file, const uint8_t *buf,
174*5113495bSYour Name 			 qdf_size_t len, int rowsize, int groupsize)
175*5113495bSYour Name {
176*5113495bSYour Name 	seq_hex_dump(file, "", DUMP_PREFIX_OFFSET, rowsize, groupsize, buf, len,
177*5113495bSYour Name 		     false);
178*5113495bSYour Name }
179*5113495bSYour Name 
180*5113495bSYour Name qdf_export_symbol(qdf_debugfs_hexdump);
181*5113495bSYour Name #else
182*5113495bSYour Name 
qdf_debugfs_hexdump(qdf_debugfs_file_t file,const uint8_t * buf,qdf_size_t len,int rowsize,int groupsize)183*5113495bSYour Name void qdf_debugfs_hexdump(qdf_debugfs_file_t file, const uint8_t *buf,
184*5113495bSYour Name 			 qdf_size_t len, int rowsize, int groupsize)
185*5113495bSYour Name {
186*5113495bSYour Name 	char *dst;
187*5113495bSYour Name 	size_t dstlen, readlen, remaining = len;
188*5113495bSYour Name 	int prefix = 0;
189*5113495bSYour Name 	size_t commitlen;
190*5113495bSYour Name 
191*5113495bSYour Name 	while (remaining > 0 && (file->size > file->count)) {
192*5113495bSYour Name 		seq_printf(file, "%.8x: ", prefix);
193*5113495bSYour Name 
194*5113495bSYour Name 		readlen = qdf_min(remaining, (qdf_size_t)rowsize);
195*5113495bSYour Name 		dstlen = seq_get_buf(file, &dst);
196*5113495bSYour Name 		hex_dump_to_buffer(buf, readlen, rowsize, groupsize, dst,
197*5113495bSYour Name 				   dstlen, false);
198*5113495bSYour Name 		commitlen = strnlen(dst, dstlen);
199*5113495bSYour Name 		seq_commit(file, commitlen);
200*5113495bSYour Name 		seq_putc(file, '\n');
201*5113495bSYour Name 
202*5113495bSYour Name 		remaining = (remaining > rowsize) ? remaining - rowsize : 0;
203*5113495bSYour Name 		buf += readlen;
204*5113495bSYour Name 		prefix += rowsize;
205*5113495bSYour Name 	}
206*5113495bSYour Name }
207*5113495bSYour Name 
208*5113495bSYour Name qdf_export_symbol(qdf_debugfs_hexdump);
209*5113495bSYour Name #endif
210*5113495bSYour Name 
qdf_debugfs_overflow(qdf_debugfs_file_t file)211*5113495bSYour Name bool qdf_debugfs_overflow(qdf_debugfs_file_t file)
212*5113495bSYour Name {
213*5113495bSYour Name 	return seq_has_overflowed(file);
214*5113495bSYour Name }
215*5113495bSYour Name 
216*5113495bSYour Name qdf_export_symbol(qdf_debugfs_overflow);
217*5113495bSYour Name 
qdf_debugfs_write(qdf_debugfs_file_t file,const uint8_t * buf,qdf_size_t len)218*5113495bSYour Name void qdf_debugfs_write(qdf_debugfs_file_t file, const uint8_t *buf,
219*5113495bSYour Name 		       qdf_size_t len)
220*5113495bSYour Name {
221*5113495bSYour Name 	seq_write(file, buf, len);
222*5113495bSYour Name }
223*5113495bSYour Name 
224*5113495bSYour Name /* sequential file operation table */
225*5113495bSYour Name static const struct seq_operations __qdf_debugfs_seq_ops = {
226*5113495bSYour Name 	.start = qdf_debugfs_seq_start,
227*5113495bSYour Name 	.next = qdf_debugfs_seq_next,
228*5113495bSYour Name 	.stop = qdf_debugfs_seq_stop,
229*5113495bSYour Name 	.show = qdf_debugfs_seq_show,
230*5113495bSYour Name };
231*5113495bSYour Name 
232*5113495bSYour Name /* .open() */
qdf_seq_open(struct inode * inode,struct file * file)233*5113495bSYour Name static int qdf_seq_open(struct inode *inode, struct file *file)
234*5113495bSYour Name {
235*5113495bSYour Name 	void *private = inode->i_private;
236*5113495bSYour Name 	struct seq_file *seq;
237*5113495bSYour Name 	int rc;
238*5113495bSYour Name 
239*5113495bSYour Name 	/**
240*5113495bSYour Name 	 * Note: seq_open() will allocate a struct seq_file and store its
241*5113495bSYour Name 	 * pointer in @file->private_data. It warns if private_data is not NULL.
242*5113495bSYour Name 	 */
243*5113495bSYour Name 
244*5113495bSYour Name 	rc = seq_open(file, &__qdf_debugfs_seq_ops);
245*5113495bSYour Name 
246*5113495bSYour Name 	if (rc == 0) {
247*5113495bSYour Name 		seq = file->private_data;
248*5113495bSYour Name 		seq->private = private;
249*5113495bSYour Name 	}
250*5113495bSYour Name 
251*5113495bSYour Name 	return rc;
252*5113495bSYour Name }
253*5113495bSYour Name 
254*5113495bSYour Name /* .write() */
qdf_seq_write(struct file * filp,const char __user * ubuf,size_t len,loff_t * ppos)255*5113495bSYour Name static ssize_t qdf_seq_write(struct file *filp, const char __user *ubuf,
256*5113495bSYour Name 			     size_t len, loff_t *ppos)
257*5113495bSYour Name {
258*5113495bSYour Name 	struct qdf_debugfs_fops *fops;
259*5113495bSYour Name 	struct seq_file *seq;
260*5113495bSYour Name 	u8 *buf;
261*5113495bSYour Name 	ssize_t rc = 0;
262*5113495bSYour Name 
263*5113495bSYour Name 	if (len == 0)
264*5113495bSYour Name 		return 0;
265*5113495bSYour Name 
266*5113495bSYour Name 	seq = filp->private_data;
267*5113495bSYour Name 	fops = seq->private;
268*5113495bSYour Name 	if (fops && fops->write) {
269*5113495bSYour Name 		buf = qdf_mem_malloc(len + 1);
270*5113495bSYour Name 		if (buf) {
271*5113495bSYour Name 			buf[len] = '\0';
272*5113495bSYour Name 			rc = simple_write_to_buffer(buf, len, ppos, ubuf, len);
273*5113495bSYour Name 			fops->write(fops->priv, buf, len + 1);
274*5113495bSYour Name 			qdf_mem_free(buf);
275*5113495bSYour Name 		}
276*5113495bSYour Name 	}
277*5113495bSYour Name 
278*5113495bSYour Name 	return rc;
279*5113495bSYour Name }
280*5113495bSYour Name 
281*5113495bSYour Name /* debugfs file operation table */
282*5113495bSYour Name static const struct file_operations __qdf_debugfs_fops = {
283*5113495bSYour Name 	.owner = THIS_MODULE,
284*5113495bSYour Name 	.open = qdf_seq_open,
285*5113495bSYour Name 	.read = seq_read,
286*5113495bSYour Name 	.llseek = seq_lseek,
287*5113495bSYour Name 	.release = seq_release,
288*5113495bSYour Name 	.write = qdf_seq_write,
289*5113495bSYour Name };
290*5113495bSYour Name 
qdf_debugfs_create_dir(const char * name,qdf_dentry_t parent)291*5113495bSYour Name qdf_dentry_t qdf_debugfs_create_dir(const char *name, qdf_dentry_t parent)
292*5113495bSYour Name {
293*5113495bSYour Name 	qdf_dentry_t dir;
294*5113495bSYour Name 
295*5113495bSYour Name 	if (!name)
296*5113495bSYour Name 		return NULL;
297*5113495bSYour Name 	if (!parent)
298*5113495bSYour Name 		parent = qdf_debugfs_get_root();
299*5113495bSYour Name 
300*5113495bSYour Name 	dir = debugfs_create_dir(name, parent);
301*5113495bSYour Name 
302*5113495bSYour Name 	if (IS_ERR_OR_NULL(dir)) {
303*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
304*5113495bSYour Name 			  "%s creation failed", name);
305*5113495bSYour Name 		dir = NULL;
306*5113495bSYour Name 	}
307*5113495bSYour Name 
308*5113495bSYour Name 	return dir;
309*5113495bSYour Name }
310*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_dir);
311*5113495bSYour Name 
qdf_debugfs_create_file(const char * name,uint16_t mode,qdf_dentry_t parent,struct qdf_debugfs_fops * fops)312*5113495bSYour Name qdf_dentry_t qdf_debugfs_create_file(const char *name, uint16_t mode,
313*5113495bSYour Name 				     qdf_dentry_t parent,
314*5113495bSYour Name 				     struct qdf_debugfs_fops *fops)
315*5113495bSYour Name {
316*5113495bSYour Name 	qdf_dentry_t file;
317*5113495bSYour Name 	umode_t filemode;
318*5113495bSYour Name 
319*5113495bSYour Name 	if (!name || !fops)
320*5113495bSYour Name 		return NULL;
321*5113495bSYour Name 
322*5113495bSYour Name 	if (!parent)
323*5113495bSYour Name 		parent = qdf_debugfs_get_root();
324*5113495bSYour Name 
325*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
326*5113495bSYour Name 	file = debugfs_create_file(name, filemode, parent, fops,
327*5113495bSYour Name 				   &__qdf_debugfs_fops);
328*5113495bSYour Name 
329*5113495bSYour Name 	if (IS_ERR_OR_NULL(file)) {
330*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
331*5113495bSYour Name 			  "%s creation failed 0x%pK", name, file);
332*5113495bSYour Name 		file = NULL;
333*5113495bSYour Name 	}
334*5113495bSYour Name 
335*5113495bSYour Name 	return file;
336*5113495bSYour Name }
337*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_file);
338*5113495bSYour Name 
qdf_debugfs_create_u8(const char * name,uint16_t mode,qdf_dentry_t parent,u8 * value)339*5113495bSYour Name void qdf_debugfs_create_u8(const char *name, uint16_t mode,
340*5113495bSYour Name 			   qdf_dentry_t parent, u8 *value)
341*5113495bSYour Name {
342*5113495bSYour Name 	umode_t filemode;
343*5113495bSYour Name 
344*5113495bSYour Name 	if (!name)
345*5113495bSYour Name 		return;
346*5113495bSYour Name 
347*5113495bSYour Name 	if (!parent)
348*5113495bSYour Name 		parent = qdf_debugfs_get_root();
349*5113495bSYour Name 
350*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
351*5113495bSYour Name 	debugfs_create_u8(name, filemode, parent, value);
352*5113495bSYour Name }
353*5113495bSYour Name 
qdf_debugfs_create_u16(const char * name,uint16_t mode,qdf_dentry_t parent,u16 * value)354*5113495bSYour Name void qdf_debugfs_create_u16(const char *name, uint16_t mode,
355*5113495bSYour Name 			    qdf_dentry_t parent, u16 *value)
356*5113495bSYour Name {
357*5113495bSYour Name 	umode_t filemode;
358*5113495bSYour Name 
359*5113495bSYour Name 	if (!name)
360*5113495bSYour Name 		return;
361*5113495bSYour Name 
362*5113495bSYour Name 	if (!parent)
363*5113495bSYour Name 		parent = qdf_debugfs_get_root();
364*5113495bSYour Name 
365*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
366*5113495bSYour Name 	debugfs_create_u16(name, filemode, parent, value);
367*5113495bSYour Name }
368*5113495bSYour Name 
369*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_u16);
370*5113495bSYour Name 
qdf_debugfs_create_u32(const char * name,uint16_t mode,qdf_dentry_t parent,u32 * value)371*5113495bSYour Name void qdf_debugfs_create_u32(const char *name,
372*5113495bSYour Name 			    uint16_t mode,
373*5113495bSYour Name 			    qdf_dentry_t parent, u32 *value)
374*5113495bSYour Name {
375*5113495bSYour Name 	umode_t filemode;
376*5113495bSYour Name 
377*5113495bSYour Name 	if (!name)
378*5113495bSYour Name 		return;
379*5113495bSYour Name 
380*5113495bSYour Name 	if (!parent)
381*5113495bSYour Name 		parent = qdf_debugfs_get_root();
382*5113495bSYour Name 
383*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
384*5113495bSYour Name 	debugfs_create_u32(name, filemode, parent, value);
385*5113495bSYour Name }
386*5113495bSYour Name 
387*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_u32);
388*5113495bSYour Name 
qdf_debugfs_create_u64(const char * name,uint16_t mode,qdf_dentry_t parent,u64 * value)389*5113495bSYour Name void qdf_debugfs_create_u64(const char *name, uint16_t mode,
390*5113495bSYour Name 			    qdf_dentry_t parent, u64 *value)
391*5113495bSYour Name {
392*5113495bSYour Name 	umode_t filemode;
393*5113495bSYour Name 
394*5113495bSYour Name 	if (!name)
395*5113495bSYour Name 		return;
396*5113495bSYour Name 
397*5113495bSYour Name 	if (!parent)
398*5113495bSYour Name 		parent = qdf_debugfs_get_root();
399*5113495bSYour Name 
400*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
401*5113495bSYour Name 	debugfs_create_u64(name, filemode, parent, value);
402*5113495bSYour Name }
403*5113495bSYour Name 
404*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_u64);
405*5113495bSYour Name 
qdf_debugfs_create_atomic(const char * name,uint16_t mode,qdf_dentry_t parent,qdf_atomic_t * value)406*5113495bSYour Name void qdf_debugfs_create_atomic(const char *name, uint16_t mode,
407*5113495bSYour Name 			       qdf_dentry_t parent, qdf_atomic_t *value)
408*5113495bSYour Name {
409*5113495bSYour Name 	umode_t filemode;
410*5113495bSYour Name 
411*5113495bSYour Name 	if (!name)
412*5113495bSYour Name 		return;
413*5113495bSYour Name 
414*5113495bSYour Name 	if (!parent)
415*5113495bSYour Name 		parent = qdf_debugfs_get_root();
416*5113495bSYour Name 
417*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
418*5113495bSYour Name 	debugfs_create_atomic_t(name, filemode, parent, value);
419*5113495bSYour Name }
420*5113495bSYour Name 
421*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_atomic);
422*5113495bSYour Name 
qdf_debugfs_string_show(struct seq_file * seq,void * pos)423*5113495bSYour Name static int qdf_debugfs_string_show(struct seq_file *seq, void *pos)
424*5113495bSYour Name {
425*5113495bSYour Name 	char *str = seq->private;
426*5113495bSYour Name 
427*5113495bSYour Name 	seq_puts(seq, str);
428*5113495bSYour Name 	seq_putc(seq, '\n');
429*5113495bSYour Name 
430*5113495bSYour Name 	return 0;
431*5113495bSYour Name }
432*5113495bSYour Name 
qdf_debugfs_string_open(struct inode * inode,struct file * file)433*5113495bSYour Name static int qdf_debugfs_string_open(struct inode *inode, struct file *file)
434*5113495bSYour Name {
435*5113495bSYour Name 	return single_open(file, qdf_debugfs_string_show, inode->i_private);
436*5113495bSYour Name }
437*5113495bSYour Name 
438*5113495bSYour Name static const struct file_operations qdf_string_fops = {
439*5113495bSYour Name 	.owner = THIS_MODULE,
440*5113495bSYour Name 	.open = qdf_debugfs_string_open,
441*5113495bSYour Name 	.read = seq_read,
442*5113495bSYour Name 	.llseek = seq_lseek,
443*5113495bSYour Name 	.release = single_release
444*5113495bSYour Name };
445*5113495bSYour Name 
qdf_debugfs_create_string(const char * name,uint16_t mode,qdf_dentry_t parent,char * str)446*5113495bSYour Name qdf_dentry_t qdf_debugfs_create_string(const char *name, uint16_t mode,
447*5113495bSYour Name 				       qdf_dentry_t parent, char *str)
448*5113495bSYour Name {
449*5113495bSYour Name 	umode_t filemode;
450*5113495bSYour Name 
451*5113495bSYour Name 	if (!name)
452*5113495bSYour Name 		return NULL;
453*5113495bSYour Name 
454*5113495bSYour Name 	if (!parent)
455*5113495bSYour Name 		parent = qdf_debugfs_get_root();
456*5113495bSYour Name 
457*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
458*5113495bSYour Name 	return debugfs_create_file(name, filemode, parent, str,
459*5113495bSYour Name 				   &qdf_string_fops);
460*5113495bSYour Name }
461*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_string);
462*5113495bSYour Name 
qdf_debugfs_remove_dir_recursive(qdf_dentry_t d)463*5113495bSYour Name void qdf_debugfs_remove_dir_recursive(qdf_dentry_t d)
464*5113495bSYour Name {
465*5113495bSYour Name 	debugfs_remove_recursive(d);
466*5113495bSYour Name }
467*5113495bSYour Name qdf_export_symbol(qdf_debugfs_remove_dir_recursive);
468*5113495bSYour Name 
qdf_debugfs_remove_dir(qdf_dentry_t d)469*5113495bSYour Name void qdf_debugfs_remove_dir(qdf_dentry_t d)
470*5113495bSYour Name {
471*5113495bSYour Name 	debugfs_remove(d);
472*5113495bSYour Name }
473*5113495bSYour Name qdf_export_symbol(qdf_debugfs_remove_dir);
474*5113495bSYour Name 
qdf_debugfs_remove_file(qdf_dentry_t d)475*5113495bSYour Name void qdf_debugfs_remove_file(qdf_dentry_t d)
476*5113495bSYour Name {
477*5113495bSYour Name 	debugfs_remove(d);
478*5113495bSYour Name }
479*5113495bSYour Name qdf_export_symbol(qdf_debugfs_remove_file);
480*5113495bSYour Name 
qdf_debugfs_single_show(struct seq_file * seq,void * v)481*5113495bSYour Name static int qdf_debugfs_single_show(struct seq_file *seq, void *v)
482*5113495bSYour Name {
483*5113495bSYour Name 	struct qdf_debugfs_fops *fops = seq->private;
484*5113495bSYour Name 
485*5113495bSYour Name 	if (fops && fops->show)
486*5113495bSYour Name 		fops->show(seq, fops->priv);
487*5113495bSYour Name 
488*5113495bSYour Name 	return 0;
489*5113495bSYour Name }
490*5113495bSYour Name 
491*5113495bSYour Name /* .open() */
qdf_debugfs_single_open(struct inode * inode,struct file * file)492*5113495bSYour Name static int qdf_debugfs_single_open(struct inode *inode, struct file *file)
493*5113495bSYour Name {
494*5113495bSYour Name 	return single_open(file, qdf_debugfs_single_show,
495*5113495bSYour Name 			   inode->i_private);
496*5113495bSYour Name }
497*5113495bSYour Name 
498*5113495bSYour Name /* File operations for the simplified version */
499*5113495bSYour Name static const struct file_operations qdf_debugfs_fops_simple = {
500*5113495bSYour Name 	.owner          = THIS_MODULE,
501*5113495bSYour Name 	.open           = qdf_debugfs_single_open,
502*5113495bSYour Name 	.release        = single_release,
503*5113495bSYour Name 	.read           = seq_read,
504*5113495bSYour Name 	.llseek         = seq_lseek,
505*5113495bSYour Name };
506*5113495bSYour Name 
qdf_debugfs_create_file_simplified(const char * name,uint16_t mode,qdf_dentry_t parent,struct qdf_debugfs_fops * fops)507*5113495bSYour Name qdf_dentry_t qdf_debugfs_create_file_simplified(
508*5113495bSYour Name 	const char *name, uint16_t mode,
509*5113495bSYour Name 	qdf_dentry_t parent, struct qdf_debugfs_fops *fops)
510*5113495bSYour Name {
511*5113495bSYour Name 	qdf_dentry_t file;
512*5113495bSYour Name 	umode_t filemode;
513*5113495bSYour Name 
514*5113495bSYour Name 	if (!name || !fops)
515*5113495bSYour Name 		return NULL;
516*5113495bSYour Name 
517*5113495bSYour Name 	if (!parent)
518*5113495bSYour Name 		parent = qdf_debugfs_get_root();
519*5113495bSYour Name 
520*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
521*5113495bSYour Name 	file = debugfs_create_file(name, filemode, parent, fops,
522*5113495bSYour Name 				   &qdf_debugfs_fops_simple);
523*5113495bSYour Name 
524*5113495bSYour Name 	if (IS_ERR_OR_NULL(file)) {
525*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
526*5113495bSYour Name 			  "%s creation failed 0x%pK", name, file);
527*5113495bSYour Name 		file = NULL;
528*5113495bSYour Name 	}
529*5113495bSYour Name 
530*5113495bSYour Name 	return file;
531*5113495bSYour Name }
532*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_file_simplified);
533*5113495bSYour Name 
qdf_debugfs_printer(void * priv,const char * fmt,...)534*5113495bSYour Name int qdf_debugfs_printer(void *priv, const char *fmt, ...)
535*5113495bSYour Name {
536*5113495bSYour Name 	struct seq_file *file = priv;
537*5113495bSYour Name 	va_list args;
538*5113495bSYour Name 
539*5113495bSYour Name 	va_start(args, fmt);
540*5113495bSYour Name 	seq_vprintf(file, fmt, args);
541*5113495bSYour Name 	seq_puts(file, "\n");
542*5113495bSYour Name 	va_end(args);
543*5113495bSYour Name 
544*5113495bSYour Name 	return 0;
545*5113495bSYour Name }
546*5113495bSYour Name qdf_export_symbol(qdf_debugfs_printer);
547*5113495bSYour Name 
qdf_debugfs_create_blob(const char * name,umode_t mode,qdf_dentry_t parent,qdf_debugfs_blob_wrap_t blob)548*5113495bSYour Name qdf_dentry_t qdf_debugfs_create_blob(const char *name, umode_t mode,
549*5113495bSYour Name 				     qdf_dentry_t parent,
550*5113495bSYour Name 				     qdf_debugfs_blob_wrap_t blob)
551*5113495bSYour Name {
552*5113495bSYour Name 	return debugfs_create_blob(name, mode, parent, blob);
553*5113495bSYour Name }
554*5113495bSYour Name 
555*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_blob);
556*5113495bSYour Name 
qdf_debugfs_create_entry(const char * name,uint16_t mode,qdf_dentry_t parent,qdf_entry_t data,const qdf_file_ops_t fops)557*5113495bSYour Name qdf_dentry_t qdf_debugfs_create_entry(const char *name, uint16_t mode,
558*5113495bSYour Name 				      qdf_dentry_t parent,
559*5113495bSYour Name 				      qdf_entry_t data,
560*5113495bSYour Name 				      const qdf_file_ops_t fops)
561*5113495bSYour Name {
562*5113495bSYour Name 	qdf_dentry_t file;
563*5113495bSYour Name 	umode_t filemode;
564*5113495bSYour Name 
565*5113495bSYour Name 	if (!name || !fops)
566*5113495bSYour Name 		return NULL;
567*5113495bSYour Name 
568*5113495bSYour Name 	if (!parent)
569*5113495bSYour Name 		parent = qdf_debugfs_get_root();
570*5113495bSYour Name 
571*5113495bSYour Name 	filemode = qdf_debugfs_get_filemode(mode);
572*5113495bSYour Name 	file = debugfs_create_file(name, filemode, parent, data, fops);
573*5113495bSYour Name 
574*5113495bSYour Name 	if (IS_ERR_OR_NULL(file)) {
575*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
576*5113495bSYour Name 			  "%s creation failed 0x%pK", name, file);
577*5113495bSYour Name 		file = NULL;
578*5113495bSYour Name 	}
579*5113495bSYour Name 
580*5113495bSYour Name 	return file;
581*5113495bSYour Name }
582*5113495bSYour Name 
583*5113495bSYour Name qdf_export_symbol(qdf_debugfs_create_entry);
584