mali_timeline.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  1. /*
  2. * This confidential and proprietary software may be used only as
  3. * authorised by a licensing agreement from ARM Limited
  4. * (C) COPYRIGHT 2013 ARM Limited
  5. * ALL RIGHTS RESERVED
  6. * The entire notice above must be reproduced on all authorised
  7. * copies and copies may only be made to the extent permitted
  8. * by a licensing agreement from ARM Limited.
  9. */
  10. #ifndef __MALI_TIMELINE_H__
  11. #define __MALI_TIMELINE_H__
  12. #include "mali_osk.h"
  13. #include "mali_ukk.h"
  14. #include "mali_session.h"
  15. #include "mali_kernel_common.h"
  16. #include "mali_spinlock_reentrant.h"
  17. #include "mali_sync.h"
  18. #include "mali_scheduler_types.h"
  19. /**
  20. * Soft job timeout.
  21. *
  22. * Soft jobs have to be signaled as complete after activation. Normally this is done by user space,
  23. * but in order to guarantee that every soft job is completed, we also have a timer.
  24. */
  25. #define MALI_TIMELINE_TIMEOUT_HZ ((u32) (HZ * 3 / 2)) /* 1500 ms. */
  26. /**
  27. * Timeline type.
  28. */
  29. typedef enum mali_timeline_id {
  30. MALI_TIMELINE_GP = MALI_UK_TIMELINE_GP, /**< GP job timeline. */
  31. MALI_TIMELINE_PP = MALI_UK_TIMELINE_PP, /**< PP job timeline. */
  32. MALI_TIMELINE_SOFT = MALI_UK_TIMELINE_SOFT, /**< Soft job timeline. */
  33. MALI_TIMELINE_MAX = MALI_UK_TIMELINE_MAX
  34. } mali_timeline_id;
  35. /**
  36. * Used by trackers that should not be added to a timeline (@ref mali_timeline_system_add_tracker).
  37. */
  38. #define MALI_TIMELINE_NONE MALI_TIMELINE_MAX
  39. /**
  40. * Tracker type.
  41. */
  42. typedef enum mali_timeline_tracker_type {
  43. MALI_TIMELINE_TRACKER_GP = 0, /**< Tracker used by GP jobs. */
  44. MALI_TIMELINE_TRACKER_PP = 1, /**< Tracker used by PP jobs. */
  45. MALI_TIMELINE_TRACKER_SOFT = 2, /**< Tracker used by soft jobs. */
  46. MALI_TIMELINE_TRACKER_WAIT = 3, /**< Tracker used for fence wait. */
  47. MALI_TIMELINE_TRACKER_SYNC = 4, /**< Tracker used for sync fence. */
  48. MALI_TIMELINE_TRACKER_MAX = 5,
  49. } mali_timeline_tracker_type;
  50. /**
  51. * Tracker activation error.
  52. */
  53. typedef u32 mali_timeline_activation_error;
  54. #define MALI_TIMELINE_ACTIVATION_ERROR_NONE 0
  55. #define MALI_TIMELINE_ACTIVATION_ERROR_SYNC_BIT (1<<1)
  56. #define MALI_TIMELINE_ACTIVATION_ERROR_FATAL_BIT (1<<0)
  57. /**
  58. * Type used to represent a point on a timeline.
  59. */
  60. typedef u32 mali_timeline_point;
  61. /**
  62. * Used to represent that no point on a timeline.
  63. */
  64. #define MALI_TIMELINE_NO_POINT ((mali_timeline_point) 0)
  65. /**
  66. * The maximum span of points on a timeline. A timeline will be considered full if the difference
  67. * between the oldest and newest points is equal or larger to this value.
  68. */
  69. #define MALI_TIMELINE_MAX_POINT_SPAN 65536
  70. /**
  71. * Magic value used to assert on validity of trackers.
  72. */
  73. #define MALI_TIMELINE_TRACKER_MAGIC 0xabcdabcd
  74. struct mali_timeline;
  75. struct mali_timeline_waiter;
  76. struct mali_timeline_tracker;
  77. /**
  78. * Timeline fence.
  79. */
  80. struct mali_timeline_fence {
  81. mali_timeline_point points[MALI_TIMELINE_MAX]; /**< For each timeline, a point or MALI_TIMELINE_NO_POINT. */
  82. s32 sync_fd; /**< A file descriptor representing a sync fence, or -1. */
  83. };
  84. /**
  85. * Timeline system.
  86. *
  87. * The Timeline system has a set of timelines associated with a session.
  88. */
  89. struct mali_timeline_system {
  90. struct mali_spinlock_reentrant *spinlock; /**< Spin lock protecting the timeline system */
  91. struct mali_timeline *timelines[MALI_TIMELINE_MAX]; /**< The timelines in this system */
  92. /* Single-linked list of unused waiter objects. Uses the tracker_next field in tracker. */
  93. struct mali_timeline_waiter *waiter_empty_list;
  94. struct mali_session_data *session; /**< Session that owns this system. */
  95. mali_bool timer_enabled; /**< Set to MALI_TRUE if soft job timer should be enabled, MALI_FALSE if not. */
  96. _mali_osk_wait_queue_t *wait_queue; /**< Wait queue. */
  97. #if defined(CONFIG_SYNC)
  98. struct sync_timeline *signaled_sync_tl; /**< Special sync timeline used to create pre-signaled sync fences */
  99. #endif /* defined(CONFIG_SYNC) */
  100. };
  101. /**
  102. * Timeline. Each Timeline system will have MALI_TIMELINE_MAX timelines.
  103. */
  104. struct mali_timeline {
  105. mali_timeline_point point_next; /**< The next available point. */
  106. mali_timeline_point point_oldest; /**< The oldest point not released. */
  107. /* Double-linked list of trackers. Sorted in ascending order by tracker->time_number with
  108. * tail pointing to the tracker with the oldest time. */
  109. struct mali_timeline_tracker *tracker_head;
  110. struct mali_timeline_tracker *tracker_tail;
  111. /* Double-linked list of waiters. Sorted in ascending order by waiter->time_number_wait
  112. * with tail pointing to the waiter with oldest wait time. */
  113. struct mali_timeline_waiter *waiter_head;
  114. struct mali_timeline_waiter *waiter_tail;
  115. struct mali_timeline_system *system; /**< Timeline system this timeline belongs to. */
  116. enum mali_timeline_id id; /**< Timeline type. */
  117. #if defined(CONFIG_SYNC)
  118. struct sync_timeline *sync_tl; /**< Sync timeline that corresponds to this timeline. */
  119. #endif /* defined(CONFIG_SYNC) */
  120. /* The following fields are used to time out soft job trackers. */
  121. _mali_osk_wq_delayed_work_t *delayed_work;
  122. mali_bool timer_active;
  123. };
  124. /**
  125. * Timeline waiter.
  126. */
  127. struct mali_timeline_waiter {
  128. mali_timeline_point point; /**< Point on timeline we are waiting for to be released. */
  129. struct mali_timeline_tracker *tracker; /**< Tracker that is waiting. */
  130. struct mali_timeline_waiter *timeline_next; /**< Next waiter on timeline's waiter list. */
  131. struct mali_timeline_waiter *timeline_prev; /**< Previous waiter on timeline's waiter list. */
  132. struct mali_timeline_waiter *tracker_next; /**< Next waiter on tracker's waiter list. */
  133. };
  134. /**
  135. * Timeline tracker.
  136. */
  137. struct mali_timeline_tracker {
  138. MALI_DEBUG_CODE(u32 magic); /**< Should always be MALI_TIMELINE_TRACKER_MAGIC for a valid tracker. */
  139. mali_timeline_point point; /**< Point on timeline for this tracker */
  140. struct mali_timeline_tracker *timeline_next; /**< Next tracker on timeline's tracker list */
  141. struct mali_timeline_tracker *timeline_prev; /**< Previous tracker on timeline's tracker list */
  142. u32 trigger_ref_count; /**< When zero tracker will be activated */
  143. mali_timeline_activation_error activation_error; /**< Activation error. */
  144. struct mali_timeline_fence fence; /**< Fence used to create this tracker */
  145. /* Single-linked list of waiters. Sorted in order of insertions with
  146. * tail pointing to first waiter. */
  147. struct mali_timeline_waiter *waiter_head;
  148. struct mali_timeline_waiter *waiter_tail;
  149. #if defined(CONFIG_SYNC)
  150. /* These are only used if the tracker is waiting on a sync fence. */
  151. struct mali_timeline_waiter *waiter_sync; /**< A direct pointer to timeline waiter representing sync fence. */
  152. struct sync_fence_waiter sync_fence_waiter; /**< Used to connect sync fence and tracker in sync fence wait callback. */
  153. struct sync_fence *sync_fence; /**< The sync fence this tracker is waiting on. */
  154. _mali_osk_list_t sync_fence_cancel_list; /**< List node used to cancel sync fence waiters. */
  155. #endif /* defined(CONFIG_SYNC) */
  156. struct mali_timeline_system *system; /**< Timeline system. */
  157. struct mali_timeline *timeline; /**< Timeline, or NULL if not on a timeline. */
  158. enum mali_timeline_tracker_type type; /**< Type of tracker. */
  159. void *job; /**< Owner of tracker. */
  160. /* The following fields are used to time out soft job trackers. */
  161. u32 os_tick_create;
  162. u32 os_tick_activate;
  163. mali_bool timer_active;
  164. };
  165. /**
  166. * What follows is a set of functions to check the state of a timeline and to determine where on a
  167. * timeline a given point is. Most of these checks will translate the timeline so the oldest point
  168. * on the timeline is aligned with zero. Remember that all of these calculation are done on
  169. * unsigned integers.
  170. *
  171. * The following example illustrates the three different states a point can be in. The timeline has
  172. * been translated to put the oldest point at zero:
  173. *
  174. *
  175. *
  176. * [ point is in forbidden zone ]
  177. * 64k wide
  178. * MALI_TIMELINE_MAX_POINT_SPAN
  179. *
  180. * [ point is on timeline ) ( point is released ]
  181. *
  182. * 0--------------------------##############################--------------------2^32 - 1
  183. * ^ ^
  184. * \ |
  185. * oldest point on timeline |
  186. * \
  187. * next point on timeline
  188. */
  189. /**
  190. * Compare two timeline points
  191. *
  192. * Returns true if a is after b, false if a is before or equal to b.
  193. *
  194. * This funcion ignores MALI_TIMELINE_MAX_POINT_SPAN. Wrapping is supported and
  195. * the result will be correct if the points is less then UINT_MAX/2 apart.
  196. *
  197. * @param a Point on timeline
  198. * @param b Point on timeline
  199. * @return MALI_TRUE if a is after b
  200. */
  201. MALI_STATIC_INLINE mali_bool mali_timeline_point_after(mali_timeline_point a, mali_timeline_point b)
  202. {
  203. return 0 > ((s32)b) - ((s32)a);
  204. }
  205. /**
  206. * Check if a point is on timeline. A point is on a timeline if it is greater than, or equal to,
  207. * the oldest point, and less than the next point.
  208. *
  209. * @param timeline Timeline.
  210. * @param point Point on timeline.
  211. * @return MALI_TRUE if point is on timeline, MALI_FALSE if not.
  212. */
  213. MALI_STATIC_INLINE mali_bool mali_timeline_is_point_on(struct mali_timeline *timeline, mali_timeline_point point)
  214. {
  215. MALI_DEBUG_ASSERT_POINTER(timeline);
  216. MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
  217. return (point - timeline->point_oldest) < (timeline->point_next - timeline->point_oldest);
  218. }
  219. /**
  220. * Check if a point has been released. A point is released if it is older than the oldest point on
  221. * the timeline, newer than the next point, and also not in the forbidden zone.
  222. *
  223. * @param timeline Timeline.
  224. * @param point Point on timeline.
  225. * @return MALI_TRUE if point has been release, MALI_FALSE if not.
  226. */
  227. MALI_STATIC_INLINE mali_bool mali_timeline_is_point_released(struct mali_timeline *timeline, mali_timeline_point point)
  228. {
  229. mali_timeline_point point_normalized;
  230. mali_timeline_point next_normalized;
  231. MALI_DEBUG_ASSERT_POINTER(timeline);
  232. MALI_DEBUG_ASSERT(MALI_TIMELINE_NO_POINT != point);
  233. point_normalized = point - timeline->point_oldest;
  234. next_normalized = timeline->point_next - timeline->point_oldest;
  235. return point_normalized > (next_normalized + MALI_TIMELINE_MAX_POINT_SPAN);
  236. }
  237. /**
  238. * Check if a point is valid. A point is valid if is on the timeline or has been released.
  239. *
  240. * @param timeline Timeline.
  241. * @param point Point on timeline.
  242. * @return MALI_TRUE if point is valid, MALI_FALSE if not.
  243. */
  244. MALI_STATIC_INLINE mali_bool mali_timeline_is_point_valid(struct mali_timeline *timeline, mali_timeline_point point)
  245. {
  246. MALI_DEBUG_ASSERT_POINTER(timeline);
  247. return mali_timeline_is_point_on(timeline, point) || mali_timeline_is_point_released(timeline, point);
  248. }
  249. /**
  250. * Check if timeline is empty (has no points on it). A timeline is empty if next == oldest.
  251. *
  252. * @param timeline Timeline.
  253. * @return MALI_TRUE if timeline is empty, MALI_FALSE if not.
  254. */
  255. MALI_STATIC_INLINE mali_bool mali_timeline_is_empty(struct mali_timeline *timeline)
  256. {
  257. MALI_DEBUG_ASSERT_POINTER(timeline);
  258. return timeline->point_next == timeline->point_oldest;
  259. }
  260. /**
  261. * Check if timeline is full. A valid timeline cannot span more than 64k points (@ref
  262. * MALI_TIMELINE_MAX_POINT_SPAN).
  263. *
  264. * @param timeline Timeline.
  265. * @return MALI_TRUE if timeline is full, MALI_FALSE if not.
  266. */
  267. MALI_STATIC_INLINE mali_bool mali_timeline_is_full(struct mali_timeline *timeline)
  268. {
  269. MALI_DEBUG_ASSERT_POINTER(timeline);
  270. return MALI_TIMELINE_MAX_POINT_SPAN <= (timeline->point_next - timeline->point_oldest);
  271. }
  272. /**
  273. * Create a new timeline system.
  274. *
  275. * @param session The session this timeline system will belong to.
  276. * @return New timeline system.
  277. */
  278. struct mali_timeline_system *mali_timeline_system_create(struct mali_session_data *session);
  279. /**
  280. * Abort timeline system.
  281. *
  282. * This will release all pending waiters in the timeline system causing all trackers to be
  283. * activated.
  284. *
  285. * @param system Timeline system to abort all jobs from.
  286. */
  287. void mali_timeline_system_abort(struct mali_timeline_system *system);
  288. /**
  289. * Destroy an empty timeline system.
  290. *
  291. * @note @ref mali_timeline_system_abort() should be called prior to this function.
  292. *
  293. * @param system Timeline system to destroy.
  294. */
  295. void mali_timeline_system_destroy(struct mali_timeline_system *system);
  296. /**
  297. * Stop the soft job timer.
  298. *
  299. * @param system Timeline system
  300. */
  301. void mali_timeline_system_stop_timer(struct mali_timeline_system *system);
  302. /**
  303. * Add a tracker to a timeline system and optionally also on a timeline.
  304. *
  305. * Once added to the timeline system, the tracker is guaranteed to be activated. The tracker can be
  306. * activated before this function returns. Thus, it is also possible that the tracker is released
  307. * before this function returns, depending on the tracker type.
  308. *
  309. * @note Tracker must be initialized (@ref mali_timeline_tracker_init) before being added to the
  310. * timeline system.
  311. *
  312. * @param system Timeline system the tracker will be added to.
  313. * @param tracker The tracker to be added.
  314. * @param timeline_id Id of the timeline the tracker will be added to, or
  315. * MALI_TIMELINE_NONE if it should not be added on a timeline.
  316. * @return Point on timeline identifying this tracker, or MALI_TIMELINE_NO_POINT if not on timeline.
  317. */
  318. mali_timeline_point mali_timeline_system_add_tracker(struct mali_timeline_system *system,
  319. struct mali_timeline_tracker *tracker,
  320. enum mali_timeline_id timeline_id);
  321. /**
  322. * Get latest point on timeline.
  323. *
  324. * @param system Timeline system.
  325. * @param timeline_id Id of timeline to get latest point from.
  326. * @return Latest point on timeline, or MALI_TIMELINE_NO_POINT if the timeline is empty.
  327. */
  328. mali_timeline_point mali_timeline_system_get_latest_point(struct mali_timeline_system *system,
  329. enum mali_timeline_id timeline_id);
  330. /**
  331. * Initialize tracker.
  332. *
  333. * Must be called before tracker is added to timeline system (@ref mali_timeline_system_add_tracker).
  334. *
  335. * @param tracker Tracker to initialize.
  336. * @param type Type of tracker.
  337. * @param fence Fence used to set up dependencies for tracker.
  338. * @param job Pointer to job struct this tracker is associated with.
  339. */
  340. void mali_timeline_tracker_init(struct mali_timeline_tracker *tracker,
  341. mali_timeline_tracker_type type,
  342. struct mali_timeline_fence *fence,
  343. void *job);
  344. /**
  345. * Grab trigger ref count on tracker.
  346. *
  347. * This will prevent tracker from being activated until the trigger ref count reaches zero.
  348. *
  349. * @note Tracker must have been initialized (@ref mali_timeline_tracker_init).
  350. *
  351. * @param system Timeline system.
  352. * @param tracker Tracker.
  353. */
  354. void mali_timeline_system_tracker_get(struct mali_timeline_system *system, struct mali_timeline_tracker *tracker);
  355. /**
  356. * Release trigger ref count on tracker.
  357. *
  358. * If the trigger ref count reaches zero, the tracker will be activated.
  359. *
  360. * @param system Timeline system.
  361. * @param tracker Tracker.
  362. * @param activation_error Error bitmask if activated with error, or MALI_TIMELINE_ACTIVATION_ERROR_NONE if no error.
  363. * @return Scheduling bitmask.
  364. */
  365. mali_scheduler_mask mali_timeline_system_tracker_put(struct mali_timeline_system *system, struct mali_timeline_tracker *tracker, mali_timeline_activation_error activation_error);
  366. /**
  367. * Release a tracker from the timeline system.
  368. *
  369. * This is used to signal that the job being tracker is finished, either due to normal circumstances
  370. * (job complete/abort) or due to a timeout.
  371. *
  372. * We may need to schedule some subsystems after a tracker has been released and the returned
  373. * bitmask will tell us if it is necessary. If the return value is non-zero, this value needs to be
  374. * sent as an input parameter to @ref mali_scheduler_schedule_from_mask() to do the scheduling.
  375. *
  376. * @note Tracker must have been activated before being released.
  377. * @warning Not calling @ref mali_scheduler_schedule_from_mask() after releasing a tracker can lead
  378. * to a deadlock.
  379. *
  380. * @param tracker Tracker being released.
  381. * @return Scheduling bitmask.
  382. */
  383. mali_scheduler_mask mali_timeline_tracker_release(struct mali_timeline_tracker *tracker);
  384. /**
  385. * Copy data from a UK fence to a Timeline fence.
  386. *
  387. * @param fence Timeline fence.
  388. * @param uk_fence UK fence.
  389. */
  390. void mali_timeline_fence_copy_uk_fence(struct mali_timeline_fence *fence, _mali_uk_fence_t *uk_fence);
  391. #define MALI_TIMELINE_DEBUG_FUNCTIONS
  392. #if defined(MALI_TIMELINE_DEBUG_FUNCTIONS)
  393. /**
  394. * Tracker state. Used for debug printing.
  395. */
  396. typedef enum mali_timeline_tracker_state {
  397. MALI_TIMELINE_TS_INIT = 0,
  398. MALI_TIMELINE_TS_WAITING = 1,
  399. MALI_TIMELINE_TS_ACTIVE = 2,
  400. MALI_TIMELINE_TS_FINISH = 3,
  401. } mali_timeline_tracker_state;
  402. /**
  403. * Get tracker state.
  404. *
  405. * @param tracker Tracker to check.
  406. * @return State of tracker.
  407. */
  408. mali_timeline_tracker_state mali_timeline_debug_get_tracker_state(struct mali_timeline_tracker *tracker);
  409. /**
  410. * Print debug information about tracker.
  411. *
  412. * @param tracker Tracker to print.
  413. */
  414. void mali_timeline_debug_print_tracker(struct mali_timeline_tracker *tracker);
  415. /**
  416. * Print debug information about timeline.
  417. *
  418. * @param timeline Timeline to print.
  419. */
  420. void mali_timeline_debug_print_timeline(struct mali_timeline *timeline);
  421. /**
  422. * Print debug information about timeline system.
  423. *
  424. * @param system Timeline system to print.
  425. */
  426. void mali_timeline_debug_print_system(struct mali_timeline_system *system);
  427. #endif /* defined(MALI_TIMELINE_DEBUG_FUNCTIONS) */
  428. #endif /* __MALI_TIMELINE_H__ */