sde_fence.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
  6. #include <linux/sync_file.h>
  7. #include <linux/dma-fence.h>
  8. #include "msm_drv.h"
  9. #include "sde_kms.h"
  10. #include "sde_fence.h"
  11. #define TIMELINE_VAL_LENGTH 128
  12. int _dma_fence_signal_timestamp_locked(struct dma_fence *fence, ktime_t ts)
  13. {
  14. struct dma_fence_cb *cur, *tmp;
  15. struct list_head cb_list;
  16. lockdep_assert_held(fence->lock);
  17. if (unlikely(test_and_set_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &fence->flags)))
  18. return -EINVAL;
  19. /* Stash the cb_list before replacing it with the timestamp */
  20. list_replace(&fence->cb_list, &cb_list);
  21. fence->timestamp = ts;
  22. set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
  23. list_for_each_entry_safe(cur, tmp, &cb_list, node) {
  24. INIT_LIST_HEAD(&cur->node);
  25. cur->func(fence, cur);
  26. }
  27. return 0;
  28. }
  29. void *sde_sync_get(uint64_t fd)
  30. {
  31. /* force signed compare, fdget accepts an int argument */
  32. return (signed int)fd >= 0 ? sync_file_get_fence(fd) : NULL;
  33. }
  34. void sde_sync_put(void *fence)
  35. {
  36. if (fence)
  37. dma_fence_put(fence);
  38. }
  39. signed long sde_sync_wait(void *fnc, long timeout_ms)
  40. {
  41. struct dma_fence *fence = fnc;
  42. int rc;
  43. char timeline_str[TIMELINE_VAL_LENGTH];
  44. if (!fence)
  45. return -EINVAL;
  46. else if (dma_fence_is_signaled(fence))
  47. return timeout_ms ? msecs_to_jiffies(timeout_ms) : 1;
  48. rc = dma_fence_wait_timeout(fence, true,
  49. msecs_to_jiffies(timeout_ms));
  50. if (!rc || (rc == -EINVAL)) {
  51. if (fence->ops->timeline_value_str)
  52. fence->ops->timeline_value_str(fence,
  53. timeline_str, TIMELINE_VAL_LENGTH);
  54. SDE_ERROR(
  55. "fence driver name:%s timeline name:%s seqno:0x%x timeline:%s signaled:0x%x\n",
  56. fence->ops->get_driver_name(fence),
  57. fence->ops->get_timeline_name(fence),
  58. fence->seqno, timeline_str,
  59. fence->ops->signaled ?
  60. fence->ops->signaled(fence) : 0xffffffff);
  61. }
  62. return rc;
  63. }
  64. uint32_t sde_sync_get_name_prefix(void *fence)
  65. {
  66. const char *name;
  67. uint32_t i, prefix;
  68. struct dma_fence *f = fence;
  69. if (!fence)
  70. return 0;
  71. name = f->ops->get_driver_name(f);
  72. if (!name)
  73. return 0;
  74. prefix = 0x0;
  75. for (i = 0; i < sizeof(uint32_t) && name[i]; ++i)
  76. prefix = (prefix << CHAR_BIT) | name[i];
  77. return prefix;
  78. }
  79. /**
  80. * struct sde_fence - release/retire fence structure
  81. * @fence: base fence structure
  82. * @name: name of each fence- it is fence timeline + commit_count
  83. * @fence_list: list to associated this fence on timeline/context
  84. * @fd: fd attached to this fence - debugging purpose.
  85. */
  86. struct sde_fence {
  87. struct dma_fence base;
  88. struct sde_fence_context *ctx;
  89. char name[SDE_FENCE_NAME_SIZE];
  90. struct list_head fence_list;
  91. int fd;
  92. };
  93. static void sde_fence_destroy(struct kref *kref)
  94. {
  95. struct sde_fence_context *ctx;
  96. if (!kref) {
  97. SDE_ERROR("received invalid kref\n");
  98. return;
  99. }
  100. ctx = container_of(kref, struct sde_fence_context, kref);
  101. kfree(ctx);
  102. }
  103. static inline struct sde_fence *to_sde_fence(struct dma_fence *fence)
  104. {
  105. return container_of(fence, struct sde_fence, base);
  106. }
  107. static const char *sde_fence_get_driver_name(struct dma_fence *fence)
  108. {
  109. struct sde_fence *f = to_sde_fence(fence);
  110. return f->name;
  111. }
  112. static const char *sde_fence_get_timeline_name(struct dma_fence *fence)
  113. {
  114. struct sde_fence *f = to_sde_fence(fence);
  115. return f->ctx->name;
  116. }
  117. static bool sde_fence_enable_signaling(struct dma_fence *fence)
  118. {
  119. return true;
  120. }
  121. static bool sde_fence_signaled(struct dma_fence *fence)
  122. {
  123. struct sde_fence *f = to_sde_fence(fence);
  124. bool status;
  125. status = (int)((fence->seqno - f->ctx->done_count) <= 0);
  126. SDE_DEBUG("status:%d fence seq:%d and timeline:%d\n",
  127. status, fence->seqno, f->ctx->done_count);
  128. return status;
  129. }
  130. static void sde_fence_release(struct dma_fence *fence)
  131. {
  132. struct sde_fence *f;
  133. if (fence) {
  134. f = to_sde_fence(fence);
  135. kref_put(&f->ctx->kref, sde_fence_destroy);
  136. kfree(f);
  137. }
  138. }
  139. static void sde_fence_value_str(struct dma_fence *fence, char *str, int size)
  140. {
  141. if (!fence || !str)
  142. return;
  143. snprintf(str, size, "%d", fence->seqno);
  144. }
  145. static void sde_fence_timeline_value_str(struct dma_fence *fence, char *str,
  146. int size)
  147. {
  148. struct sde_fence *f = to_sde_fence(fence);
  149. if (!fence || !f->ctx || !str)
  150. return;
  151. snprintf(str, size, "%d", f->ctx->done_count);
  152. }
  153. static struct dma_fence_ops sde_fence_ops = {
  154. .get_driver_name = sde_fence_get_driver_name,
  155. .get_timeline_name = sde_fence_get_timeline_name,
  156. .enable_signaling = sde_fence_enable_signaling,
  157. .signaled = sde_fence_signaled,
  158. .wait = dma_fence_default_wait,
  159. .release = sde_fence_release,
  160. .fence_value_str = sde_fence_value_str,
  161. .timeline_value_str = sde_fence_timeline_value_str,
  162. };
  163. /**
  164. * _sde_fence_create_fd - create fence object and return an fd for it
  165. * This function is NOT thread-safe.
  166. * @timeline: Timeline to associate with fence
  167. * @val: Timeline value at which to signal the fence
  168. * Return: File descriptor on success, or error code on error
  169. */
  170. static int _sde_fence_create_fd(void *fence_ctx, uint32_t val)
  171. {
  172. struct sde_fence *sde_fence;
  173. struct sync_file *sync_file;
  174. signed int fd = -EINVAL;
  175. struct sde_fence_context *ctx = fence_ctx;
  176. if (!ctx) {
  177. SDE_ERROR("invalid context\n");
  178. goto exit;
  179. }
  180. sde_fence = kzalloc(sizeof(*sde_fence), GFP_KERNEL);
  181. if (!sde_fence)
  182. return -ENOMEM;
  183. sde_fence->ctx = fence_ctx;
  184. snprintf(sde_fence->name, SDE_FENCE_NAME_SIZE, "sde_fence:%s:%u",
  185. sde_fence->ctx->name, val);
  186. dma_fence_init(&sde_fence->base, &sde_fence_ops, &ctx->lock,
  187. ctx->context, val);
  188. kref_get(&ctx->kref);
  189. /* create fd */
  190. fd = get_unused_fd_flags(0);
  191. if (fd < 0) {
  192. SDE_ERROR("failed to get_unused_fd_flags(), %s\n",
  193. sde_fence->name);
  194. dma_fence_put(&sde_fence->base);
  195. goto exit;
  196. }
  197. /* create fence */
  198. sync_file = sync_file_create(&sde_fence->base);
  199. if (sync_file == NULL) {
  200. put_unused_fd(fd);
  201. fd = -EINVAL;
  202. SDE_ERROR("couldn't create fence, %s\n", sde_fence->name);
  203. dma_fence_put(&sde_fence->base);
  204. goto exit;
  205. }
  206. fd_install(fd, sync_file->file);
  207. sde_fence->fd = fd;
  208. spin_lock(&ctx->list_lock);
  209. list_add_tail(&sde_fence->fence_list, &ctx->fence_list_head);
  210. spin_unlock(&ctx->list_lock);
  211. exit:
  212. return fd;
  213. }
  214. struct sde_fence_context *sde_fence_init(const char *name, uint32_t drm_id)
  215. {
  216. struct sde_fence_context *ctx;
  217. if (!name) {
  218. SDE_ERROR("invalid argument(s)\n");
  219. return ERR_PTR(-EINVAL);
  220. }
  221. ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
  222. if (!ctx) {
  223. SDE_ERROR("failed to alloc fence ctx\n");
  224. return ERR_PTR(-ENOMEM);
  225. }
  226. strlcpy(ctx->name, name, ARRAY_SIZE(ctx->name));
  227. ctx->drm_id = drm_id;
  228. kref_init(&ctx->kref);
  229. ctx->context = dma_fence_context_alloc(1);
  230. spin_lock_init(&ctx->lock);
  231. spin_lock_init(&ctx->list_lock);
  232. INIT_LIST_HEAD(&ctx->fence_list_head);
  233. return ctx;
  234. }
  235. void sde_fence_deinit(struct sde_fence_context *ctx)
  236. {
  237. if (!ctx) {
  238. SDE_ERROR("invalid fence\n");
  239. return;
  240. }
  241. kref_put(&ctx->kref, sde_fence_destroy);
  242. }
  243. void sde_fence_prepare(struct sde_fence_context *ctx)
  244. {
  245. unsigned long flags;
  246. if (!ctx) {
  247. SDE_ERROR("invalid argument(s), fence %pK\n", ctx);
  248. } else {
  249. spin_lock_irqsave(&ctx->lock, flags);
  250. ++ctx->commit_count;
  251. spin_unlock_irqrestore(&ctx->lock, flags);
  252. }
  253. }
  254. static void _sde_fence_trigger(struct sde_fence_context *ctx, bool error, ktime_t ts)
  255. {
  256. unsigned long flags;
  257. struct sde_fence *fc, *next;
  258. bool is_signaled = false;
  259. kref_get(&ctx->kref);
  260. spin_lock(&ctx->list_lock);
  261. if (list_empty(&ctx->fence_list_head)) {
  262. SDE_DEBUG("nothing to trigger!\n");
  263. goto end;
  264. }
  265. list_for_each_entry_safe(fc, next, &ctx->fence_list_head, fence_list) {
  266. spin_lock_irqsave(&ctx->lock, flags);
  267. if (error)
  268. dma_fence_set_error(&fc->base, -EBUSY);
  269. is_signaled = sde_fence_signaled(&fc->base);
  270. if (is_signaled)
  271. _dma_fence_signal_timestamp_locked(&fc->base, ts);
  272. spin_unlock_irqrestore(&ctx->lock, flags);
  273. if (is_signaled) {
  274. list_del_init(&fc->fence_list);
  275. dma_fence_put(&fc->base);
  276. }
  277. }
  278. end:
  279. spin_unlock(&ctx->list_lock);
  280. kref_put(&ctx->kref, sde_fence_destroy);
  281. }
  282. int sde_fence_create(struct sde_fence_context *ctx, uint64_t *val,
  283. uint32_t offset)
  284. {
  285. uint32_t trigger_value;
  286. int fd, rc = -EINVAL;
  287. unsigned long flags;
  288. if (!ctx || !val) {
  289. SDE_ERROR("invalid argument(s), fence %d, pval %d\n",
  290. ctx != NULL, val != NULL);
  291. return rc;
  292. }
  293. /*
  294. * Allow created fences to have a constant offset with respect
  295. * to the timeline. This allows us to delay the fence signalling
  296. * w.r.t. the commit completion (e.g., an offset of +1 would
  297. * cause fences returned during a particular commit to signal
  298. * after an additional delay of one commit, rather than at the
  299. * end of the current one.
  300. */
  301. spin_lock_irqsave(&ctx->lock, flags);
  302. trigger_value = ctx->commit_count + offset;
  303. spin_unlock_irqrestore(&ctx->lock, flags);
  304. fd = _sde_fence_create_fd(ctx, trigger_value);
  305. *val = fd;
  306. SDE_DEBUG("fd:%d trigger:%d commit:%d offset:%d\n",
  307. fd, trigger_value, ctx->commit_count, offset);
  308. SDE_EVT32(ctx->drm_id, trigger_value, fd);
  309. rc = (fd >= 0) ? 0 : fd;
  310. return rc;
  311. }
  312. void sde_fence_signal(struct sde_fence_context *ctx, ktime_t ts,
  313. enum sde_fence_event fence_event)
  314. {
  315. unsigned long flags;
  316. if (!ctx) {
  317. SDE_ERROR("invalid ctx, %pK\n", ctx);
  318. return;
  319. }
  320. spin_lock_irqsave(&ctx->lock, flags);
  321. if (fence_event == SDE_FENCE_RESET_TIMELINE) {
  322. if ((int)(ctx->done_count - ctx->commit_count) < 0) {
  323. SDE_DEBUG(
  324. "timeline reset attempt! done count:%d commit:%d\n",
  325. ctx->done_count, ctx->commit_count);
  326. ctx->done_count = ctx->commit_count;
  327. SDE_EVT32(ctx->drm_id, ctx->done_count,
  328. ctx->commit_count, ktime_to_us(ts),
  329. fence_event, SDE_EVTLOG_FUNC_CASE1);
  330. } else {
  331. spin_unlock_irqrestore(&ctx->lock, flags);
  332. return;
  333. }
  334. } else if ((int)(ctx->done_count - ctx->commit_count) < 0) {
  335. ++ctx->done_count;
  336. SDE_DEBUG("fence_signal:done count:%d commit count:%d\n",
  337. ctx->done_count, ctx->commit_count);
  338. } else {
  339. SDE_ERROR("extra signal attempt! done count:%d commit:%d\n",
  340. ctx->done_count, ctx->commit_count);
  341. SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
  342. ktime_to_us(ts), fence_event, SDE_EVTLOG_FATAL);
  343. spin_unlock_irqrestore(&ctx->lock, flags);
  344. return;
  345. }
  346. spin_unlock_irqrestore(&ctx->lock, flags);
  347. SDE_EVT32(ctx->drm_id, ctx->done_count, ctx->commit_count,
  348. ktime_to_us(ts));
  349. _sde_fence_trigger(ctx, (fence_event == SDE_FENCE_SIGNAL_ERROR), ts);
  350. }
  351. void sde_fence_timeline_status(struct sde_fence_context *ctx,
  352. struct drm_mode_object *drm_obj)
  353. {
  354. char *obj_name;
  355. if (!ctx || !drm_obj) {
  356. SDE_ERROR("invalid input params\n");
  357. return;
  358. }
  359. switch (drm_obj->type) {
  360. case DRM_MODE_OBJECT_CRTC:
  361. obj_name = "crtc";
  362. break;
  363. case DRM_MODE_OBJECT_CONNECTOR:
  364. obj_name = "connector";
  365. break;
  366. default:
  367. obj_name = "unknown";
  368. break;
  369. }
  370. SDE_ERROR("drm obj:%s id:%d type:0x%x done_count:%d commit_count:%d\n",
  371. obj_name, drm_obj->id, drm_obj->type, ctx->done_count,
  372. ctx->commit_count);
  373. }
  374. void sde_fence_list_dump(struct dma_fence *fence, struct seq_file **s)
  375. {
  376. char timeline_str[TIMELINE_VAL_LENGTH];
  377. if (fence->ops->timeline_value_str)
  378. fence->ops->timeline_value_str(fence,
  379. timeline_str, TIMELINE_VAL_LENGTH);
  380. seq_printf(*s, "fence name:%s timeline name:%s seqno:0x%x timeline:%s signaled:0x%x\n",
  381. fence->ops->get_driver_name(fence),
  382. fence->ops->get_timeline_name(fence),
  383. fence->seqno, timeline_str,
  384. fence->ops->signaled ?
  385. fence->ops->signaled(fence) : 0xffffffff);
  386. }
  387. void sde_debugfs_timeline_dump(struct sde_fence_context *ctx,
  388. struct drm_mode_object *drm_obj, struct seq_file **s)
  389. {
  390. char *obj_name;
  391. struct sde_fence *fc, *next;
  392. struct dma_fence *fence;
  393. if (!ctx || !drm_obj) {
  394. SDE_ERROR("invalid input params\n");
  395. return;
  396. }
  397. switch (drm_obj->type) {
  398. case DRM_MODE_OBJECT_CRTC:
  399. obj_name = "crtc";
  400. break;
  401. case DRM_MODE_OBJECT_CONNECTOR:
  402. obj_name = "connector";
  403. break;
  404. default:
  405. obj_name = "unknown";
  406. break;
  407. }
  408. seq_printf(*s, "drm obj:%s id:%d type:0x%x done_count:%d commit_count:%d\n",
  409. obj_name, drm_obj->id, drm_obj->type, ctx->done_count,
  410. ctx->commit_count);
  411. spin_lock(&ctx->list_lock);
  412. list_for_each_entry_safe(fc, next, &ctx->fence_list_head, fence_list) {
  413. fence = &fc->base;
  414. sde_fence_list_dump(fence, s);
  415. }
  416. spin_unlock(&ctx->list_lock);
  417. }