intel_wakeref.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. * SPDX-License-Identifier: MIT
  3. *
  4. * Copyright © 2019 Intel Corporation
  5. */
  6. #include <linux/wait_bit.h>
  7. #include <drm/drm_print.h>
  8. #include "intel_runtime_pm.h"
  9. #include "intel_wakeref.h"
  10. #include "i915_drv.h"
  11. int __intel_wakeref_get_first(struct intel_wakeref *wf)
  12. {
  13. intel_wakeref_t wakeref;
  14. int ret = 0;
  15. wakeref = intel_runtime_pm_get(&wf->i915->runtime_pm);
  16. /*
  17. * Treat get/put as different subclasses, as we may need to run
  18. * the put callback from under the shrinker and do not want to
  19. * cross-contanimate that callback with any extra work performed
  20. * upon acquiring the wakeref.
  21. */
  22. mutex_lock_nested(&wf->mutex, SINGLE_DEPTH_NESTING);
  23. if (!atomic_read(&wf->count)) {
  24. INTEL_WAKEREF_BUG_ON(wf->wakeref);
  25. wf->wakeref = wakeref;
  26. wakeref = NULL;
  27. ret = wf->ops->get(wf);
  28. if (ret) {
  29. wakeref = xchg(&wf->wakeref, NULL);
  30. wake_up_var(&wf->wakeref);
  31. goto unlock;
  32. }
  33. smp_mb__before_atomic(); /* release wf->count */
  34. }
  35. atomic_inc(&wf->count);
  36. INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
  37. unlock:
  38. mutex_unlock(&wf->mutex);
  39. if (unlikely(wakeref))
  40. intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
  41. return ret;
  42. }
  43. static void ____intel_wakeref_put_last(struct intel_wakeref *wf)
  44. {
  45. intel_wakeref_t wakeref = NULL;
  46. INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0);
  47. if (unlikely(!atomic_dec_and_test(&wf->count)))
  48. goto unlock;
  49. /* ops->put() must reschedule its own release on error/deferral */
  50. if (likely(!wf->ops->put(wf))) {
  51. INTEL_WAKEREF_BUG_ON(!wf->wakeref);
  52. wakeref = xchg(&wf->wakeref, NULL);
  53. wake_up_var(&wf->wakeref);
  54. }
  55. unlock:
  56. mutex_unlock(&wf->mutex);
  57. if (wakeref)
  58. intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
  59. }
  60. void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags)
  61. {
  62. INTEL_WAKEREF_BUG_ON(delayed_work_pending(&wf->work));
  63. /* Assume we are not in process context and so cannot sleep. */
  64. if (flags & INTEL_WAKEREF_PUT_ASYNC || !mutex_trylock(&wf->mutex)) {
  65. mod_delayed_work(wf->i915->unordered_wq, &wf->work,
  66. FIELD_GET(INTEL_WAKEREF_PUT_DELAY_MASK, flags));
  67. return;
  68. }
  69. ____intel_wakeref_put_last(wf);
  70. }
  71. static void __intel_wakeref_put_work(struct work_struct *wrk)
  72. {
  73. struct intel_wakeref *wf = container_of(wrk, typeof(*wf), work.work);
  74. if (atomic_add_unless(&wf->count, -1, 1))
  75. return;
  76. mutex_lock(&wf->mutex);
  77. ____intel_wakeref_put_last(wf);
  78. }
  79. void __intel_wakeref_init(struct intel_wakeref *wf,
  80. struct drm_i915_private *i915,
  81. const struct intel_wakeref_ops *ops,
  82. struct intel_wakeref_lockclass *key,
  83. const char *name)
  84. {
  85. wf->i915 = i915;
  86. wf->ops = ops;
  87. __mutex_init(&wf->mutex, "wakeref.mutex", &key->mutex);
  88. atomic_set(&wf->count, 0);
  89. wf->wakeref = NULL;
  90. INIT_DELAYED_WORK(&wf->work, __intel_wakeref_put_work);
  91. lockdep_init_map(&wf->work.work.lockdep_map,
  92. "wakeref.work", &key->work, 0);
  93. #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_WAKEREF)
  94. if (!wf->debug.class)
  95. ref_tracker_dir_init(&wf->debug, INTEL_REFTRACK_DEAD_COUNT, "intel_wakeref");
  96. #endif
  97. }
  98. int intel_wakeref_wait_for_idle(struct intel_wakeref *wf)
  99. {
  100. int err;
  101. might_sleep();
  102. err = wait_var_event_killable(&wf->wakeref,
  103. !intel_wakeref_is_active(wf));
  104. if (err)
  105. return err;
  106. intel_wakeref_unlock_wait(wf);
  107. return 0;
  108. }
  109. static void wakeref_auto_timeout(struct timer_list *t)
  110. {
  111. struct intel_wakeref_auto *wf = timer_container_of(wf, t, timer);
  112. intel_wakeref_t wakeref;
  113. unsigned long flags;
  114. if (!refcount_dec_and_lock_irqsave(&wf->count, &wf->lock, &flags))
  115. return;
  116. wakeref = xchg(&wf->wakeref, NULL);
  117. spin_unlock_irqrestore(&wf->lock, flags);
  118. intel_runtime_pm_put(&wf->i915->runtime_pm, wakeref);
  119. }
  120. void intel_wakeref_auto_init(struct intel_wakeref_auto *wf,
  121. struct drm_i915_private *i915)
  122. {
  123. spin_lock_init(&wf->lock);
  124. timer_setup(&wf->timer, wakeref_auto_timeout, 0);
  125. refcount_set(&wf->count, 0);
  126. wf->wakeref = NULL;
  127. wf->i915 = i915;
  128. }
  129. void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout)
  130. {
  131. unsigned long flags;
  132. if (!timeout) {
  133. if (timer_delete_sync(&wf->timer))
  134. wakeref_auto_timeout(&wf->timer);
  135. return;
  136. }
  137. /* Our mission is that we only extend an already active wakeref */
  138. assert_rpm_wakelock_held(&wf->i915->runtime_pm);
  139. if (!refcount_inc_not_zero(&wf->count)) {
  140. spin_lock_irqsave(&wf->lock, flags);
  141. if (!refcount_inc_not_zero(&wf->count)) {
  142. INTEL_WAKEREF_BUG_ON(wf->wakeref);
  143. wf->wakeref =
  144. intel_runtime_pm_get_if_in_use(&wf->i915->runtime_pm);
  145. refcount_set(&wf->count, 1);
  146. }
  147. spin_unlock_irqrestore(&wf->lock, flags);
  148. }
  149. /*
  150. * If we extend a pending timer, we will only get a single timer
  151. * callback and so need to cancel the local inc by running the
  152. * elided callback to keep the wf->count balanced.
  153. */
  154. if (mod_timer(&wf->timer, jiffies + timeout))
  155. wakeref_auto_timeout(&wf->timer);
  156. }
  157. void intel_wakeref_auto_fini(struct intel_wakeref_auto *wf)
  158. {
  159. intel_wakeref_auto(wf, 0);
  160. INTEL_WAKEREF_BUG_ON(wf->wakeref);
  161. }
  162. void intel_ref_tracker_show(struct ref_tracker_dir *dir,
  163. struct drm_printer *p)
  164. {
  165. const size_t buf_size = PAGE_SIZE;
  166. char *buf, *sb, *se;
  167. size_t count;
  168. buf = kmalloc(buf_size, GFP_NOWAIT);
  169. if (!buf)
  170. return;
  171. count = ref_tracker_dir_snprint(dir, buf, buf_size);
  172. if (!count)
  173. goto free;
  174. /* printk does not like big buffers, so we split it */
  175. for (sb = buf; *sb; sb = se + 1) {
  176. se = strchrnul(sb, '\n');
  177. drm_printf(p, "%.*s", (int)(se - sb + 1), sb);
  178. if (!*se)
  179. break;
  180. }
  181. if (count >= buf_size)
  182. drm_printf(p, "\n...dropped %zd extra bytes of leak report.\n",
  183. count + 1 - buf_size);
  184. free:
  185. kfree(buf);
  186. }