1 1.4 riastrad /* $NetBSD: intel_wakeref.h,v 1.4 2021/12/19 12:33:57 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* 4 1.1 riastrad * SPDX-License-Identifier: MIT 5 1.1 riastrad * 6 1.1 riastrad * Copyright 2019 Intel Corporation 7 1.1 riastrad */ 8 1.1 riastrad 9 1.1 riastrad #ifndef INTEL_WAKEREF_H 10 1.1 riastrad #define INTEL_WAKEREF_H 11 1.1 riastrad 12 1.1 riastrad #include <linux/atomic.h> 13 1.1 riastrad #include <linux/bits.h> 14 1.1 riastrad #include <linux/lockdep.h> 15 1.1 riastrad #include <linux/mutex.h> 16 1.1 riastrad #include <linux/refcount.h> 17 1.1 riastrad #include <linux/stackdepot.h> 18 1.1 riastrad #include <linux/timer.h> 19 1.1 riastrad #include <linux/workqueue.h> 20 1.1 riastrad 21 1.3 riastrad #include <drm/drm_wait_netbsd.h> /* XXX */ 22 1.3 riastrad 23 1.1 riastrad #if IS_ENABLED(CONFIG_DRM_I915_DEBUG) 24 1.1 riastrad #define INTEL_WAKEREF_BUG_ON(expr) BUG_ON(expr) 25 1.1 riastrad #else 26 1.1 riastrad #define INTEL_WAKEREF_BUG_ON(expr) BUILD_BUG_ON_INVALID(expr) 27 1.1 riastrad #endif 28 1.1 riastrad 29 1.1 riastrad struct intel_runtime_pm; 30 1.1 riastrad struct intel_wakeref; 31 1.1 riastrad 32 1.1 riastrad typedef depot_stack_handle_t intel_wakeref_t; 33 1.1 riastrad 34 1.1 riastrad struct intel_wakeref_ops { 35 1.1 riastrad int (*get)(struct intel_wakeref *wf); 36 1.1 riastrad int (*put)(struct intel_wakeref *wf); 37 1.1 riastrad }; 38 1.1 riastrad 39 1.1 riastrad struct intel_wakeref { 40 1.1 riastrad atomic_t count; 41 1.1 riastrad struct mutex mutex; 42 1.1 riastrad 43 1.1 riastrad intel_wakeref_t wakeref; 44 1.3 riastrad drm_waitqueue_t wq; 45 1.1 riastrad 46 1.1 riastrad struct intel_runtime_pm *rpm; 47 1.1 riastrad const struct intel_wakeref_ops *ops; 48 1.1 riastrad 49 1.1 riastrad struct work_struct work; 50 1.1 riastrad }; 51 1.1 riastrad 52 1.1 riastrad struct intel_wakeref_lockclass { 53 1.1 riastrad struct lock_class_key mutex; 54 1.1 riastrad struct lock_class_key work; 55 1.1 riastrad }; 56 1.1 riastrad 57 1.1 riastrad void __intel_wakeref_init(struct intel_wakeref *wf, 58 1.1 riastrad struct intel_runtime_pm *rpm, 59 1.1 riastrad const struct intel_wakeref_ops *ops, 60 1.1 riastrad struct intel_wakeref_lockclass *key); 61 1.1 riastrad #define intel_wakeref_init(wf, rpm, ops) do { \ 62 1.1 riastrad static struct intel_wakeref_lockclass __key; \ 63 1.1 riastrad \ 64 1.1 riastrad __intel_wakeref_init((wf), (rpm), (ops), &__key); \ 65 1.1 riastrad } while (0) 66 1.1 riastrad 67 1.4 riastrad void intel_wakeref_fini(struct intel_wakeref *); 68 1.4 riastrad 69 1.1 riastrad int __intel_wakeref_get_first(struct intel_wakeref *wf); 70 1.1 riastrad void __intel_wakeref_put_last(struct intel_wakeref *wf, unsigned long flags); 71 1.1 riastrad 72 1.1 riastrad /** 73 1.1 riastrad * intel_wakeref_get: Acquire the wakeref 74 1.1 riastrad * @wf: the wakeref 75 1.1 riastrad * 76 1.1 riastrad * Acquire a hold on the wakeref. The first user to do so, will acquire 77 1.1 riastrad * the runtime pm wakeref and then call the @fn underneath the wakeref 78 1.1 riastrad * mutex. 79 1.1 riastrad * 80 1.1 riastrad * Note that @fn is allowed to fail, in which case the runtime-pm wakeref 81 1.1 riastrad * will be released and the acquisition unwound, and an error reported. 82 1.1 riastrad * 83 1.1 riastrad * Returns: 0 if the wakeref was acquired successfully, or a negative error 84 1.1 riastrad * code otherwise. 85 1.1 riastrad */ 86 1.1 riastrad static inline int 87 1.1 riastrad intel_wakeref_get(struct intel_wakeref *wf) 88 1.1 riastrad { 89 1.1 riastrad might_sleep(); 90 1.1 riastrad if (unlikely(!atomic_inc_not_zero(&wf->count))) 91 1.1 riastrad return __intel_wakeref_get_first(wf); 92 1.1 riastrad 93 1.1 riastrad return 0; 94 1.1 riastrad } 95 1.1 riastrad 96 1.1 riastrad /** 97 1.1 riastrad * __intel_wakeref_get: Acquire the wakeref, again 98 1.1 riastrad * @wf: the wakeref 99 1.1 riastrad * 100 1.1 riastrad * Increment the wakeref counter, only valid if it is already held by 101 1.1 riastrad * the caller. 102 1.1 riastrad * 103 1.1 riastrad * See intel_wakeref_get(). 104 1.1 riastrad */ 105 1.1 riastrad static inline void 106 1.1 riastrad __intel_wakeref_get(struct intel_wakeref *wf) 107 1.1 riastrad { 108 1.1 riastrad INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); 109 1.1 riastrad atomic_inc(&wf->count); 110 1.1 riastrad } 111 1.1 riastrad 112 1.1 riastrad /** 113 1.1 riastrad * intel_wakeref_get_if_in_use: Acquire the wakeref 114 1.1 riastrad * @wf: the wakeref 115 1.1 riastrad * 116 1.1 riastrad * Acquire a hold on the wakeref, but only if the wakeref is already 117 1.1 riastrad * active. 118 1.1 riastrad * 119 1.1 riastrad * Returns: true if the wakeref was acquired, false otherwise. 120 1.1 riastrad */ 121 1.1 riastrad static inline bool 122 1.1 riastrad intel_wakeref_get_if_active(struct intel_wakeref *wf) 123 1.1 riastrad { 124 1.1 riastrad return atomic_inc_not_zero(&wf->count); 125 1.1 riastrad } 126 1.1 riastrad 127 1.1 riastrad /** 128 1.1 riastrad * intel_wakeref_put_flags: Release the wakeref 129 1.1 riastrad * @wf: the wakeref 130 1.1 riastrad * @flags: control flags 131 1.1 riastrad * 132 1.1 riastrad * Release our hold on the wakeref. When there are no more users, 133 1.1 riastrad * the runtime pm wakeref will be released after the @fn callback is called 134 1.1 riastrad * underneath the wakeref mutex. 135 1.1 riastrad * 136 1.1 riastrad * Note that @fn is allowed to fail, in which case the runtime-pm wakeref 137 1.1 riastrad * is retained and an error reported. 138 1.1 riastrad * 139 1.1 riastrad * Returns: 0 if the wakeref was released successfully, or a negative error 140 1.1 riastrad * code otherwise. 141 1.1 riastrad */ 142 1.1 riastrad static inline void 143 1.1 riastrad __intel_wakeref_put(struct intel_wakeref *wf, unsigned long flags) 144 1.1 riastrad #define INTEL_WAKEREF_PUT_ASYNC BIT(0) 145 1.1 riastrad { 146 1.1 riastrad INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count) <= 0); 147 1.1 riastrad if (unlikely(!atomic_add_unless(&wf->count, -1, 1))) 148 1.1 riastrad __intel_wakeref_put_last(wf, flags); 149 1.1 riastrad } 150 1.1 riastrad 151 1.1 riastrad static inline void 152 1.1 riastrad intel_wakeref_put(struct intel_wakeref *wf) 153 1.1 riastrad { 154 1.1 riastrad might_sleep(); 155 1.1 riastrad __intel_wakeref_put(wf, 0); 156 1.1 riastrad } 157 1.1 riastrad 158 1.1 riastrad static inline void 159 1.1 riastrad intel_wakeref_put_async(struct intel_wakeref *wf) 160 1.1 riastrad { 161 1.1 riastrad __intel_wakeref_put(wf, INTEL_WAKEREF_PUT_ASYNC); 162 1.1 riastrad } 163 1.1 riastrad 164 1.1 riastrad /** 165 1.1 riastrad * intel_wakeref_lock: Lock the wakeref (mutex) 166 1.1 riastrad * @wf: the wakeref 167 1.1 riastrad * 168 1.1 riastrad * Locks the wakeref to prevent it being acquired or released. New users 169 1.1 riastrad * can still adjust the counter, but the wakeref itself (and callback) 170 1.1 riastrad * cannot be acquired or released. 171 1.1 riastrad */ 172 1.1 riastrad static inline void 173 1.1 riastrad intel_wakeref_lock(struct intel_wakeref *wf) 174 1.1 riastrad __acquires(wf->mutex) 175 1.1 riastrad { 176 1.1 riastrad mutex_lock(&wf->mutex); 177 1.1 riastrad } 178 1.1 riastrad 179 1.1 riastrad /** 180 1.1 riastrad * intel_wakeref_unlock: Unlock the wakeref 181 1.1 riastrad * @wf: the wakeref 182 1.1 riastrad * 183 1.1 riastrad * Releases a previously acquired intel_wakeref_lock(). 184 1.1 riastrad */ 185 1.1 riastrad static inline void 186 1.1 riastrad intel_wakeref_unlock(struct intel_wakeref *wf) 187 1.1 riastrad __releases(wf->mutex) 188 1.1 riastrad { 189 1.1 riastrad mutex_unlock(&wf->mutex); 190 1.1 riastrad } 191 1.1 riastrad 192 1.1 riastrad /** 193 1.1 riastrad * intel_wakeref_unlock_wait: Wait until the active callback is complete 194 1.1 riastrad * @wf: the wakeref 195 1.1 riastrad * 196 1.1 riastrad * Waits for the active callback (under the @wf->mutex or another CPU) is 197 1.1 riastrad * complete. 198 1.1 riastrad */ 199 1.1 riastrad static inline void 200 1.1 riastrad intel_wakeref_unlock_wait(struct intel_wakeref *wf) 201 1.1 riastrad { 202 1.1 riastrad mutex_lock(&wf->mutex); 203 1.1 riastrad mutex_unlock(&wf->mutex); 204 1.1 riastrad flush_work(&wf->work); 205 1.1 riastrad } 206 1.1 riastrad 207 1.1 riastrad /** 208 1.1 riastrad * intel_wakeref_is_active: Query whether the wakeref is currently held 209 1.1 riastrad * @wf: the wakeref 210 1.1 riastrad * 211 1.1 riastrad * Returns: true if the wakeref is currently held. 212 1.1 riastrad */ 213 1.1 riastrad static inline bool 214 1.1 riastrad intel_wakeref_is_active(const struct intel_wakeref *wf) 215 1.1 riastrad { 216 1.1 riastrad return READ_ONCE(wf->wakeref); 217 1.1 riastrad } 218 1.1 riastrad 219 1.1 riastrad /** 220 1.1 riastrad * __intel_wakeref_defer_park: Defer the current park callback 221 1.1 riastrad * @wf: the wakeref 222 1.1 riastrad */ 223 1.1 riastrad static inline void 224 1.1 riastrad __intel_wakeref_defer_park(struct intel_wakeref *wf) 225 1.1 riastrad { 226 1.1 riastrad lockdep_assert_held(&wf->mutex); 227 1.1 riastrad INTEL_WAKEREF_BUG_ON(atomic_read(&wf->count)); 228 1.1 riastrad atomic_set_release(&wf->count, 1); 229 1.1 riastrad } 230 1.1 riastrad 231 1.1 riastrad /** 232 1.1 riastrad * intel_wakeref_wait_for_idle: Wait until the wakeref is idle 233 1.1 riastrad * @wf: the wakeref 234 1.1 riastrad * 235 1.1 riastrad * Wait for the earlier asynchronous release of the wakeref. Note 236 1.1 riastrad * this will wait for any third party as well, so make sure you only wait 237 1.1 riastrad * when you have control over the wakeref and trust no one else is acquiring 238 1.1 riastrad * it. 239 1.1 riastrad * 240 1.1 riastrad * Return: 0 on success, error code if killed. 241 1.1 riastrad */ 242 1.1 riastrad int intel_wakeref_wait_for_idle(struct intel_wakeref *wf); 243 1.1 riastrad 244 1.1 riastrad struct intel_wakeref_auto { 245 1.1 riastrad struct intel_runtime_pm *rpm; 246 1.1 riastrad struct timer_list timer; 247 1.1 riastrad intel_wakeref_t wakeref; 248 1.1 riastrad spinlock_t lock; 249 1.1 riastrad refcount_t count; 250 1.1 riastrad }; 251 1.1 riastrad 252 1.1 riastrad /** 253 1.1 riastrad * intel_wakeref_auto: Delay the runtime-pm autosuspend 254 1.1 riastrad * @wf: the wakeref 255 1.1 riastrad * @timeout: relative timeout in jiffies 256 1.1 riastrad * 257 1.1 riastrad * The runtime-pm core uses a suspend delay after the last wakeref 258 1.1 riastrad * is released before triggering runtime suspend of the device. That 259 1.1 riastrad * delay is configurable via sysfs with little regard to the device 260 1.1 riastrad * characteristics. Instead, we want to tune the autosuspend based on our 261 1.1 riastrad * HW knowledge. intel_wakeref_auto() delays the sleep by the supplied 262 1.1 riastrad * timeout. 263 1.1 riastrad * 264 1.1 riastrad * Pass @timeout = 0 to cancel a previous autosuspend by executing the 265 1.1 riastrad * suspend immediately. 266 1.1 riastrad */ 267 1.1 riastrad void intel_wakeref_auto(struct intel_wakeref_auto *wf, unsigned long timeout); 268 1.1 riastrad 269 1.1 riastrad void intel_wakeref_auto_init(struct intel_wakeref_auto *wf, 270 1.1 riastrad struct intel_runtime_pm *rpm); 271 1.1 riastrad void intel_wakeref_auto_fini(struct intel_wakeref_auto *wf); 272 1.1 riastrad 273 1.1 riastrad #endif /* INTEL_WAKEREF_H */ 274