1 /* 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright © 2019 Intel Corporation 5 */ 6 7 #ifndef INTEL_WAKEREF_H 8 #define INTEL_WAKEREF_H 9 10 #include <linux/atomic.h> 11 #include <linux/mutex.h> 12 #include <linux/refcount.h> 13 #include <linux/stackdepot.h> 14 #include <linux/timer.h> 15 16 #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) 17 #define INTEL_WAKEREF_BUG_ON(expr) BUG_ON(expr) 18 #else 19 #define INTEL_WAKEREF_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) 20 #endif 21 22 struct intel_runtime_pm; 23 24 typedef depot_stack_handle_t intel_wakeref_t; 25 26 struct intel_wakeref { 27 atomic_t count; 28 struct mutex mutex; 29 intel_wakeref_t wakeref; 30 }; 31 32 void __intel_wakeref_init(struct intel_wakeref *wf, 33 struct lock_class_key *key); 34 #define intel_wakeref_init(wf) do { \ 35 static struct lock_class_key __key; \ 36 \ 37 __intel_wakeref_init((wf), &__key); \ 38 } while (0) 39 40 int __intel_wakeref_get_first(struct intel_runtime_pm *rpm, 41 struct intel_wakeref *wf, 42 int (*fn)(struct intel_wakeref *wf)); 43 int __intel_wakeref_put_last(struct intel_runtime_pm *rpm, 44 struct intel_wakeref *wf, 45 int (*fn)(struct intel_wakeref *wf)); 46 47 /** 48 * intel_wakeref_get: Acquire the wakeref 49 * @i915: the drm_i915_private device 50 * @wf: the wakeref 51 * @fn: callback for acquired the wakeref, called only on first acquire. 52 * 53 * Acquire a hold on the wakeref. The first user to do so, will acquire 54 * the runtime pm wakeref and then call the @fn underneath the wakeref 55 * mutex. 56 * 57 * Note that @fn is allowed to fail, in which case the runtime-pm wakeref 58 * will be released and the acquisition unwound, and an error reported. 59 * 60 * Returns: 0 if the wakeref was acquired successfully, or a negative error 61 * code otherwise. 62 */ 63 static inline int 64 intel_wakeref_get(struct intel_runtime_pm *rpm, 65 struct intel_wakeref *wf, 66 int (*fn)(struct intel_wakeref *wf)) 67 { 68 if (unlikely(!atomic_inc_not_zero(&wf->count))) 69 return __intel_wakeref_get_first(rpm, wf, fn); 70 71 return 0; 72 } 73 74 /** 75 * intel_wakeref_get_if_in_use: Acquire the wakeref 76 * @wf: the wakeref 77 * 78 * Acquire a hold on the wakeref, but only if the wakeref is already 79 * active. 80 * 81 * Returns: true if the wakeref was acquired, false otherwise. 82 */ 83 static inline bool 84 intel_wakeref_get_if_active(struct intel_wakeref *wf) 85 { 86 return atomic_inc_not_zero(&wf->count); 87 } 88 89 /** 90 * intel_wakeref_put: Release the wakeref 91 * @i915: the drm_i915_private device 92 * @wf: the wakeref 93 * @fn: callback for releasing the wakeref, called only on final release. 94 * 95 * Release our hold on the wakeref. When there are no more users, 96 * the runtime pm wakeref will be released after the @fn callback is called 97 * underneath the wakeref mutex. 98 * 99 * Note that @fn is allowed to fail, in which case the runtime-pm wakeref 100 * is retained and an error reported. 101 * 102 * Returns: 0 if the wakeref was released successfully, or a negative error 103 * code otherwise. 104 */ 105 static inline int 106 intel_wakeref_put(struct intel_runtime_pm *rpm, 107 struct intel_wakeref *wf, 108 int (*fn)(struct intel_wakeref *wf)) 109 { 110 INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); 111 if (atomic_dec_and_mutex_lock(&wf->count, &wf->mutex)) 112 return __intel_wakeref_put_last(rpm, wf, fn); 113 114 return 0; 115 } 116 117 /** 118 * intel_wakeref_lock: Lock the wakeref (mutex) 119 * @wf: the wakeref 120 * 121 * Locks the wakeref to prevent it being acquired or released. New users 122 * can still adjust the counter, but the wakeref itself (and callback) 123 * cannot be acquired or released. 124 */ 125 static inline void 126 intel_wakeref_lock(struct intel_wakeref *wf) 127 __acquires(wf->mutex) 128 { 129 mutex_lock(&wf->mutex); 130 } 131 132 /** 133 * intel_wakeref_unlock: Unlock the wakeref 134 * @wf: the wakeref 135 * 136 * Releases a previously acquired intel_wakeref_lock(). 137 */ 138 static inline void 139 intel_wakeref_unlock(struct intel_wakeref *wf) 140 __releases(wf->mutex) 141 { 142 mutex_unlock(&wf->mutex); 143 } 144 145 /** 146 * intel_wakeref_is_active: Query whether the wakeref is currently held 147 * @wf: the wakeref 148 * 149 * Returns: true if the wakeref is currently held. 150 */ 151 static inline bool 152 intel_wakeref_is_active(const struct intel_wakeref *wf) 153 { 154 return READ_ONCE(wf->wakeref); 155 } 156 157 struct intel_wakeref_auto { 158 struct intel_runtime_pm *rpm; 159 struct timer_list timer; 160 intel_wakeref_t wakeref; 161 spinlock_t lock; 162 refcount_t count; 163 }; 164 165 /** 166 * intel_wakeref_auto: Delay the runtime-pm autosuspend 167 * @wf: the wakeref 168 * @timeout: relative timeout in jiffies 169 * 170 * The runtime-pm core uses a suspend delay after the last wakeref 171 * is released before triggering runtime suspend of the device. That 172 * delay is configurable via sysfs with little regard to the device 173 * characteristics. Instead, we want to tune the autosuspend based on our 174 * HW knowledge. intel_wakeref_auto() delays the sleep by the supplied 175 * timeout. 176 * 177 * Pass @timeout = 0 to cancel a previous autosuspend by executing the 178 * suspend immediately. 179 */ 180 void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout); 181 182 void intel_wakeref_auto_init(struct intel_wakeref_auto *wf, 183 struct intel_runtime_pm *rpm); 184 void intel_wakeref_auto_fini(struct intel_wakeref_auto *wf); 185 186 #endif /* INTEL_WAKEREF_H */ 187