123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- /*
- * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
- *
- * Permission to use, copy, modify, and/or distribute this software for
- * any purpose with or without fee is hereby granted, provided that the
- * above copyright notice and this permission notice appear in all
- * copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
- * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
- * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
- * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- * PERFORMANCE OF THIS SOFTWARE.
- */
- /**
- * DOC: qdf_perf
- * This file provides OS dependent perf API's.
- */
- #include <linux/version.h>
- #include <linux/kernel.h>
- #include <linux/uaccess.h>
- #include <linux/fs.h>
- #include <linux/proc_fs.h>
- #include <linux/vmalloc.h>
- #include <linux/list.h>
- #include <linux/spinlock.h>
- #include <qdf_perf.h>
- #include <qdf_module.h>
- #ifdef QCA_PERF_PROFILING
- qdf_perf_entry_t perf_root = {{0, 0} };
- /**
- * qdf_perfmod_init() - Module init
- *
- * return: int
- */
- int
- qdf_perfmod_init(void)
- {
- QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
- "Perf Debug Module Init");
- INIT_LIST_HEAD(&perf_root.list);
- INIT_LIST_HEAD(&perf_root.child);
- perf_root.proc = proc_mkdir(PROCFS_PERF_DIRNAME, 0);
- return 0;
- }
- qdf_export_symbol(qdf_perfmod_init);
- /**
- * qdf_perfmod_exit() - Module exit
- *
- * Return: none
- */
- void
- qdf_perfmod_exit(void)
- {
- QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
- "Perf Debug Module Exit");
- remove_proc_entry(PROCFS_PERF_DIRNAME, 0);
- }
- qdf_export_symbol(qdf_perfmod_exit);
- /**
- * __qdf_perf_init() - Create the perf entry
- * @parent: parent perf id
- * @id_name: name of perf id
- * @type: type of perf counter
- *
- * return: perf id
- */
- qdf_perf_id_t
- __qdf_perf_init(qdf_perf_id_t parent, uint8_t *id_name,
- qdf_perf_cntr_t type)
- {
- qdf_perf_entry_t *entry = NULL;
- qdf_perf_entry_t *pentry = PERF_ENTRY(parent);
- if (type >= CNTR_LAST) {
- QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
- "%s:%s Invalid perf-type", __FILE__, __func__);
- goto done;
- }
- if (!pentry)
- pentry = &perf_root;
- entry = kmalloc(sizeof(struct qdf_perf_entry), GFP_ATOMIC);
- if (!entry) {
- QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
- " Out of Memory,:%s", __func__);
- return NULL;
- }
- memset(entry, 0, sizeof(struct qdf_perf_entry));
- INIT_LIST_HEAD(&entry->list);
- INIT_LIST_HEAD(&entry->child);
- spin_lock_init(&entry->lock_irq);
- list_add_tail(&entry->list, &pentry->child);
- entry->name = id_name;
- entry->type = type;
- if (type == CNTR_GROUP) {
- entry->proc = proc_mkdir(id_name, pentry->proc);
- goto done;
- }
- entry->parent = pentry;
- entry->proc = create_proc_entry(id_name, S_IFREG|S_IRUGO|S_IWUSR,
- pentry->proc);
- entry->proc->data = entry;
- entry->proc->read_proc = api_tbl[type].proc_read;
- entry->proc->write_proc = api_tbl[type].proc_write;
- /*
- * Initialize the Event with default values
- */
- api_tbl[type].init(entry, api_tbl[type].def_val);
- done:
- return entry;
- }
- qdf_export_symbol(__qdf_perf_init);
- /**
- * __qdf_perf_destroy - Destroy the perf entry
- * @id: pointer to qdf_perf_id_t
- *
- * @return: bool
- */
- bool __qdf_perf_destroy(qdf_perf_id_t id)
- {
- qdf_perf_entry_t *entry = PERF_ENTRY(id),
- *parent = entry->parent;
- if (!list_empty(&entry->child)) {
- QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_ERROR,
- "Child's are alive, Can't delete");
- return A_FALSE;
- }
- remove_proc_entry(entry->name, parent->proc);
- list_del(&entry->list);
- vfree(entry);
- return true;
- }
- qdf_export_symbol(__qdf_perf_destroy);
- /**
- * __qdf_perf_start - Start the sampling
- * @id: Instance of qdf_perf_id_t
- *
- * Returns: none
- */
- void __qdf_perf_start(qdf_perf_id_t id)
- {
- qdf_perf_entry_t *entry = PERF_ENTRY(id);
- api_tbl[entry->type].sample(entry, 0);
- }
- qdf_export_symbol(__qdf_perf_start);
- /**
- * __qdf_perf_end - Stop sampling
- * @id: Instance of qdf_perf_id_t
- *
- * Returns: none
- */
- void __qdf_perf_end(qdf_perf_id_t id)
- {
- qdf_perf_entry_t *entry = PERF_ENTRY(id);
- api_tbl[entry->type].sample(entry, 1);
- }
- qdf_export_symbol(__qdf_perf_end);
- #endif /* QCA_PERF_PROFILING */
|