/drivers/media/video/samsung/mali/common/mali_kernel_profiling.c

https://github.com/yjwong/samsung-kernel-c1 · C · 305 lines · 230 code · 58 blank · 17 comment · 37 complexity · 30121a32adbb729bf3deeae7c721f52a MD5 · raw file

  1. /*
  2. * Copyright (C) 2010-2011 ARM Limited. All rights reserved.
  3. *
  4. * This program is free software and is provided to you under the terms of the GNU General Public License version 2
  5. * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
  6. *
  7. * A copy of the licence is included with the program, and can also be obtained from Free Software
  8. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  9. */
  10. #include "mali_kernel_common.h"
  11. #include "mali_osk.h"
  12. #include "mali_osk_mali.h"
  13. #include "mali_ukk.h"
  14. #include "mali_timestamp.h"
  15. #include "mali_kernel_profiling.h"
  16. typedef struct mali_profiling_entry
  17. {
  18. u64 timestamp;
  19. u32 event_id;
  20. u32 data[5];
  21. } mali_profiling_entry;
  22. typedef enum mali_profiling_state
  23. {
  24. MALI_PROFILING_STATE_UNINITIALIZED,
  25. MALI_PROFILING_STATE_IDLE,
  26. MALI_PROFILING_STATE_RUNNING,
  27. MALI_PROFILING_STATE_RETURN,
  28. } mali_profiling_state;
  29. static _mali_osk_lock_t *lock = NULL;
  30. static mali_profiling_state prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
  31. static mali_profiling_entry* profile_entries = NULL;
  32. static u32 profile_entry_count = 0;
  33. static _mali_osk_atomic_t profile_insert_index;
  34. static _mali_osk_atomic_t profile_entries_written;
  35. static mali_bool mali_profiling_default_enable = MALI_FALSE;
  36. _mali_osk_errcode_t _mali_profiling_init(mali_bool auto_start)
  37. {
  38. profile_entries = NULL;
  39. profile_entry_count = 0;
  40. _mali_osk_atomic_init(&profile_insert_index, 0);
  41. _mali_osk_atomic_init(&profile_entries_written, 0);
  42. lock = _mali_osk_lock_init( _MALI_OSK_LOCKFLAG_SPINLOCK | _MALI_OSK_LOCKFLAG_NONINTERRUPTABLE, 0, 0 );
  43. if (NULL == lock)
  44. {
  45. return _MALI_OSK_ERR_FAULT;
  46. }
  47. prof_state = MALI_PROFILING_STATE_IDLE;
  48. if (MALI_TRUE == auto_start)
  49. {
  50. u32 limit = MALI_PROFILING_MAX_BUFFER_ENTRIES; /* Use maximum buffer size */
  51. mali_profiling_default_enable = MALI_TRUE; /* save this so user space can query this on their startup */
  52. if (_MALI_OSK_ERR_OK != _mali_profiling_start(&limit))
  53. {
  54. return _MALI_OSK_ERR_FAULT;
  55. }
  56. }
  57. return _MALI_OSK_ERR_OK;
  58. }
  59. void _mali_profiling_term(void)
  60. {
  61. prof_state = MALI_PROFILING_STATE_UNINITIALIZED;
  62. /* wait for all elements to be completely inserted into array */
  63. while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written))
  64. {
  65. /* do nothing */;
  66. }
  67. if (NULL != profile_entries)
  68. {
  69. _mali_osk_vfree(profile_entries);
  70. profile_entries = NULL;
  71. }
  72. if (NULL != lock)
  73. {
  74. _mali_osk_lock_term(lock);
  75. lock = NULL;
  76. }
  77. }
  78. inline _mali_osk_errcode_t _mali_profiling_start(u32 * limit)
  79. {
  80. _mali_osk_errcode_t ret;
  81. _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
  82. if (prof_state != MALI_PROFILING_STATE_IDLE)
  83. {
  84. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  85. return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
  86. }
  87. if (*limit > MALI_PROFILING_MAX_BUFFER_ENTRIES)
  88. {
  89. *limit = MALI_PROFILING_MAX_BUFFER_ENTRIES;
  90. }
  91. profile_entries = _mali_osk_valloc(*limit * sizeof(mali_profiling_entry));
  92. profile_entry_count = *limit;
  93. if (NULL == profile_entries)
  94. {
  95. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  96. return _MALI_OSK_ERR_NOMEM;
  97. }
  98. ret = _mali_timestamp_reset();
  99. if (ret == _MALI_OSK_ERR_OK)
  100. {
  101. prof_state = MALI_PROFILING_STATE_RUNNING;
  102. }
  103. else
  104. {
  105. _mali_osk_vfree(profile_entries);
  106. profile_entries = NULL;
  107. }
  108. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  109. return ret;
  110. }
  111. inline _mali_osk_errcode_t _mali_profiling_add_event(u32 event_id, u32 data0, u32 data1, u32 data2, u32 data3, u32 data4)
  112. {
  113. u32 cur_index = _mali_osk_atomic_inc_return(&profile_insert_index) - 1;
  114. if (prof_state != MALI_PROFILING_STATE_RUNNING || cur_index >= profile_entry_count)
  115. {
  116. /*
  117. * Not in recording mode, or buffer is full
  118. * Decrement index again, and early out
  119. */
  120. _mali_osk_atomic_dec(&profile_insert_index);
  121. return _MALI_OSK_ERR_FAULT;
  122. }
  123. profile_entries[cur_index].timestamp = _mali_timestamp_get();
  124. profile_entries[cur_index].event_id = event_id;
  125. profile_entries[cur_index].data[0] = data0;
  126. profile_entries[cur_index].data[1] = data1;
  127. profile_entries[cur_index].data[2] = data2;
  128. profile_entries[cur_index].data[3] = data3;
  129. profile_entries[cur_index].data[4] = data4;
  130. _mali_osk_atomic_inc(&profile_entries_written);
  131. return _MALI_OSK_ERR_OK;
  132. }
  133. inline _mali_osk_errcode_t _mali_profiling_stop(u32 * count)
  134. {
  135. _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
  136. if (prof_state != MALI_PROFILING_STATE_RUNNING)
  137. {
  138. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  139. return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
  140. }
  141. /* go into return state (user to retreive events), no more events will be added after this */
  142. prof_state = MALI_PROFILING_STATE_RETURN;
  143. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  144. /* wait for all elements to be completely inserted into array */
  145. while (_mali_osk_atomic_read(&profile_insert_index) != _mali_osk_atomic_read(&profile_entries_written))
  146. {
  147. /* do nothing */;
  148. }
  149. *count = _mali_osk_atomic_read(&profile_insert_index);
  150. return _MALI_OSK_ERR_OK;
  151. }
  152. inline u32 _mali_profiling_get_count(void)
  153. {
  154. u32 retval = 0;
  155. _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
  156. if (prof_state == MALI_PROFILING_STATE_RETURN)
  157. {
  158. retval = _mali_osk_atomic_read(&profile_entries_written);
  159. }
  160. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  161. return retval;
  162. }
  163. inline _mali_osk_errcode_t _mali_profiling_get_event(u32 index, u64* timestamp, u32* event_id, u32 data[5])
  164. {
  165. _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
  166. if (prof_state != MALI_PROFILING_STATE_RETURN)
  167. {
  168. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  169. return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
  170. }
  171. if (index >= _mali_osk_atomic_read(&profile_entries_written))
  172. {
  173. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  174. return _MALI_OSK_ERR_FAULT;
  175. }
  176. *timestamp = profile_entries[index].timestamp;
  177. *event_id = profile_entries[index].event_id;
  178. data[0] = profile_entries[index].data[0];
  179. data[1] = profile_entries[index].data[1];
  180. data[2] = profile_entries[index].data[2];
  181. data[3] = profile_entries[index].data[3];
  182. data[4] = profile_entries[index].data[4];
  183. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  184. return _MALI_OSK_ERR_OK;
  185. }
  186. inline _mali_osk_errcode_t _mali_profiling_clear(void)
  187. {
  188. _mali_osk_lock_wait(lock, _MALI_OSK_LOCKMODE_RW);
  189. if (prof_state != MALI_PROFILING_STATE_RETURN)
  190. {
  191. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  192. return _MALI_OSK_ERR_INVALID_ARGS; /* invalid to call this function in this state */
  193. }
  194. prof_state = MALI_PROFILING_STATE_IDLE;
  195. profile_entry_count = 0;
  196. _mali_osk_atomic_init(&profile_insert_index, 0);
  197. _mali_osk_atomic_init(&profile_entries_written, 0);
  198. if (NULL != profile_entries)
  199. {
  200. _mali_osk_vfree(profile_entries);
  201. profile_entries = NULL;
  202. }
  203. _mali_osk_lock_signal(lock, _MALI_OSK_LOCKMODE_RW);
  204. return _MALI_OSK_ERR_OK;
  205. }
  206. mali_bool _mali_profiling_is_recording(void)
  207. {
  208. return prof_state == MALI_PROFILING_STATE_RUNNING ? MALI_TRUE : MALI_FALSE;
  209. }
  210. mali_bool _mali_profiling_have_recording(void)
  211. {
  212. return prof_state == MALI_PROFILING_STATE_RETURN ? MALI_TRUE : MALI_FALSE;
  213. }
  214. void _mali_profiling_set_default_enable_state(mali_bool enable)
  215. {
  216. mali_profiling_default_enable = enable;
  217. }
  218. mali_bool _mali_profiling_get_default_enable_state(void)
  219. {
  220. return mali_profiling_default_enable;
  221. }
  222. _mali_osk_errcode_t _mali_ukk_profiling_start(_mali_uk_profiling_start_s *args)
  223. {
  224. return _mali_profiling_start(&args->limit);
  225. }
  226. _mali_osk_errcode_t _mali_ukk_profiling_add_event(_mali_uk_profiling_add_event_s *args)
  227. {
  228. /* Always add process and thread identificator in the first two data elements for events from user space */
  229. return _mali_profiling_add_event(args->event_id, _mali_osk_get_pid(), _mali_osk_get_tid(), args->data[2], args->data[3], args->data[4]);
  230. }
  231. _mali_osk_errcode_t _mali_ukk_profiling_stop(_mali_uk_profiling_stop_s *args)
  232. {
  233. return _mali_profiling_stop(&args->count);
  234. }
  235. _mali_osk_errcode_t _mali_ukk_profiling_get_event(_mali_uk_profiling_get_event_s *args)
  236. {
  237. return _mali_profiling_get_event(args->index, &args->timestamp, &args->event_id, args->data);
  238. }
  239. _mali_osk_errcode_t _mali_ukk_profiling_clear(_mali_uk_profiling_clear_s *args)
  240. {
  241. return _mali_profiling_clear();
  242. }
  243. _mali_osk_errcode_t _mali_ukk_profiling_get_config(_mali_uk_profiling_get_config_s *args)
  244. {
  245. args->enable_events = mali_profiling_default_enable;
  246. return _MALI_OSK_ERR_OK;
  247. }