xref: /wlan-driver/qca-wifi-host-cmn/qdf/linux/src/qdf_perf.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name  * above copyright notice and this permission notice appear in all
7*5113495bSYour Name  * copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name  */
18*5113495bSYour Name 
19*5113495bSYour Name /**
20*5113495bSYour Name  * DOC: qdf_perf
21*5113495bSYour Name  * This file provides OS dependent perf API's.
22*5113495bSYour Name  */
23*5113495bSYour Name 
24*5113495bSYour Name #include <linux/version.h>
25*5113495bSYour Name #include <linux/kernel.h>
26*5113495bSYour Name #include <linux/uaccess.h>
27*5113495bSYour Name #include <linux/fs.h>
28*5113495bSYour Name #include <linux/proc_fs.h>
29*5113495bSYour Name #include <linux/vmalloc.h>
30*5113495bSYour Name #include <linux/list.h>
31*5113495bSYour Name #include <linux/spinlock.h>
32*5113495bSYour Name 
33*5113495bSYour Name #include <qdf_perf.h>
34*5113495bSYour Name #include <qdf_module.h>
35*5113495bSYour Name #ifdef QCA_PERF_PROFILING
36*5113495bSYour Name 
37*5113495bSYour Name qdf_perf_entry_t     perf_root = {{0, 0} };
38*5113495bSYour Name 
39*5113495bSYour Name /**
40*5113495bSYour Name  * qdf_perfmod_init() - Module init
41*5113495bSYour Name  *
42*5113495bSYour Name  * return: int
43*5113495bSYour Name  */
44*5113495bSYour Name int
qdf_perfmod_init(void)45*5113495bSYour Name qdf_perfmod_init(void)
46*5113495bSYour Name {
47*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
48*5113495bSYour Name 		  "Perf Debug Module Init");
49*5113495bSYour Name 	INIT_LIST_HEAD(&perf_root.list);
50*5113495bSYour Name 	INIT_LIST_HEAD(&perf_root.child);
51*5113495bSYour Name 	perf_root.proc = proc_mkdir(PROCFS_PERF_DIRNAME, 0);
52*5113495bSYour Name 	return 0;
53*5113495bSYour Name }
54*5113495bSYour Name qdf_export_symbol(qdf_perfmod_init);
55*5113495bSYour Name 
56*5113495bSYour Name /**
57*5113495bSYour Name  * qdf_perfmod_exit() - Module exit
58*5113495bSYour Name  *
59*5113495bSYour Name  * Return: none
60*5113495bSYour Name  */
61*5113495bSYour Name void
qdf_perfmod_exit(void)62*5113495bSYour Name qdf_perfmod_exit(void)
63*5113495bSYour Name {
64*5113495bSYour Name 	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
65*5113495bSYour Name 		  "Perf Debug Module Exit");
66*5113495bSYour Name 	remove_proc_entry(PROCFS_PERF_DIRNAME, 0);
67*5113495bSYour Name }
68*5113495bSYour Name qdf_export_symbol(qdf_perfmod_exit);
69*5113495bSYour Name 
70*5113495bSYour Name /**
71*5113495bSYour Name  * __qdf_perf_init() - Create the perf entry
72*5113495bSYour Name  * @parent: parent perf id
73*5113495bSYour Name  * @id_name: name of perf id
74*5113495bSYour Name  * @type: type of perf counter
75*5113495bSYour Name  *
76*5113495bSYour Name  * return: perf id
77*5113495bSYour Name  */
78*5113495bSYour Name qdf_perf_id_t
__qdf_perf_init(qdf_perf_id_t parent,uint8_t * id_name,qdf_perf_cntr_t type)79*5113495bSYour Name __qdf_perf_init(qdf_perf_id_t parent, uint8_t *id_name,
80*5113495bSYour Name 		qdf_perf_cntr_t type)
81*5113495bSYour Name {
82*5113495bSYour Name 	qdf_perf_entry_t    *entry  = NULL;
83*5113495bSYour Name 	qdf_perf_entry_t    *pentry = PERF_ENTRY(parent);
84*5113495bSYour Name 
85*5113495bSYour Name 	if (type >= CNTR_LAST) {
86*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
87*5113495bSYour Name 			  "%s:%s Invalid perf-type", __FILE__, __func__);
88*5113495bSYour Name 		goto done;
89*5113495bSYour Name 	}
90*5113495bSYour Name 
91*5113495bSYour Name 	if (!pentry)
92*5113495bSYour Name 		pentry = &perf_root;
93*5113495bSYour Name 	entry = kmalloc(sizeof(struct qdf_perf_entry), GFP_ATOMIC);
94*5113495bSYour Name 
95*5113495bSYour Name 	if (!entry) {
96*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
97*5113495bSYour Name 			  " Out of Memory,:%s", __func__);
98*5113495bSYour Name 		return NULL;
99*5113495bSYour Name 	}
100*5113495bSYour Name 
101*5113495bSYour Name 	memset(entry, 0, sizeof(struct qdf_perf_entry));
102*5113495bSYour Name 
103*5113495bSYour Name 	INIT_LIST_HEAD(&entry->list);
104*5113495bSYour Name 	INIT_LIST_HEAD(&entry->child);
105*5113495bSYour Name 
106*5113495bSYour Name 	spin_lock_init(&entry->lock_irq);
107*5113495bSYour Name 
108*5113495bSYour Name 	list_add_tail(&entry->list, &pentry->child);
109*5113495bSYour Name 
110*5113495bSYour Name 	entry->name = id_name;
111*5113495bSYour Name 	entry->type = type;
112*5113495bSYour Name 
113*5113495bSYour Name 	if (type == CNTR_GROUP) {
114*5113495bSYour Name 		entry->proc = proc_mkdir(id_name, pentry->proc);
115*5113495bSYour Name 		goto done;
116*5113495bSYour Name 	}
117*5113495bSYour Name 
118*5113495bSYour Name 	entry->parent   = pentry;
119*5113495bSYour Name 	entry->proc     = create_proc_entry(id_name, S_IFREG|S_IRUGO|S_IWUSR,
120*5113495bSYour Name 					pentry->proc);
121*5113495bSYour Name 	entry->proc->data       = entry;
122*5113495bSYour Name 	entry->proc->read_proc  = api_tbl[type].proc_read;
123*5113495bSYour Name 	entry->proc->write_proc = api_tbl[type].proc_write;
124*5113495bSYour Name 
125*5113495bSYour Name 	/*
126*5113495bSYour Name 	 * Initialize the Event with default values
127*5113495bSYour Name 	 */
128*5113495bSYour Name 	api_tbl[type].init(entry, api_tbl[type].def_val);
129*5113495bSYour Name 
130*5113495bSYour Name done:
131*5113495bSYour Name 	return entry;
132*5113495bSYour Name }
133*5113495bSYour Name qdf_export_symbol(__qdf_perf_init);
134*5113495bSYour Name 
135*5113495bSYour Name /**
136*5113495bSYour Name  * __qdf_perf_destroy - Destroy the perf entry
137*5113495bSYour Name  * @id: pointer to qdf_perf_id_t
138*5113495bSYour Name  *
139*5113495bSYour Name  * @return: bool
140*5113495bSYour Name  */
__qdf_perf_destroy(qdf_perf_id_t id)141*5113495bSYour Name bool __qdf_perf_destroy(qdf_perf_id_t  id)
142*5113495bSYour Name {
143*5113495bSYour Name 	qdf_perf_entry_t     *entry  = PERF_ENTRY(id),
144*5113495bSYour Name 		*parent = entry->parent;
145*5113495bSYour Name 
146*5113495bSYour Name 	if (!list_empty(&entry->child)) {
147*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
148*5113495bSYour Name 			  "Child's are alive, Can't delete");
149*5113495bSYour Name 		return A_FALSE;
150*5113495bSYour Name 	}
151*5113495bSYour Name 
152*5113495bSYour Name 	remove_proc_entry(entry->name, parent->proc);
153*5113495bSYour Name 
154*5113495bSYour Name 	list_del(&entry->list);
155*5113495bSYour Name 
156*5113495bSYour Name 	vfree(entry);
157*5113495bSYour Name 
158*5113495bSYour Name 	return true;
159*5113495bSYour Name }
160*5113495bSYour Name qdf_export_symbol(__qdf_perf_destroy);
161*5113495bSYour Name 
162*5113495bSYour Name /**
163*5113495bSYour Name  * __qdf_perf_start - Start the sampling
164*5113495bSYour Name  * @id: Instance of qdf_perf_id_t
165*5113495bSYour Name  *
166*5113495bSYour Name  * Returns: none
167*5113495bSYour Name  */
__qdf_perf_start(qdf_perf_id_t id)168*5113495bSYour Name void __qdf_perf_start(qdf_perf_id_t id)
169*5113495bSYour Name {
170*5113495bSYour Name 	qdf_perf_entry_t *entry = PERF_ENTRY(id);
171*5113495bSYour Name 
172*5113495bSYour Name 	api_tbl[entry->type].sample(entry, 0);
173*5113495bSYour Name }
174*5113495bSYour Name qdf_export_symbol(__qdf_perf_start);
175*5113495bSYour Name 
176*5113495bSYour Name /**
177*5113495bSYour Name  * __qdf_perf_end - Stop sampling
178*5113495bSYour Name  * @id: Instance of qdf_perf_id_t
179*5113495bSYour Name  *
180*5113495bSYour Name  * Returns: none
181*5113495bSYour Name  */
__qdf_perf_end(qdf_perf_id_t id)182*5113495bSYour Name void __qdf_perf_end(qdf_perf_id_t id)
183*5113495bSYour Name {
184*5113495bSYour Name 	qdf_perf_entry_t *entry = PERF_ENTRY(id);
185*5113495bSYour Name 
186*5113495bSYour Name 	api_tbl[entry->type].sample(entry, 1);
187*5113495bSYour Name }
188*5113495bSYour Name qdf_export_symbol(__qdf_perf_end);
189*5113495bSYour Name 
190*5113495bSYour Name #endif /* QCA_PERF_PROFILING */
191