qdf_perf.c 4.3 KB

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