1 1.1 riastrad /* $NetBSD: intel_runtime_pm.h,v 1.2 2021/12/18 23:45:29 riastradh Exp $ */ 2 1.1 riastrad 3 1.1 riastrad /* SPDX-License-Identifier: MIT */ 4 1.1 riastrad /* 5 1.1 riastrad * Copyright 2019 Intel Corporation 6 1.1 riastrad */ 7 1.1 riastrad 8 1.1 riastrad #ifndef __INTEL_RUNTIME_PM_H__ 9 1.1 riastrad #define __INTEL_RUNTIME_PM_H__ 10 1.1 riastrad 11 1.1 riastrad #include <linux/types.h> 12 1.1 riastrad 13 1.1 riastrad #include "display/intel_display.h" 14 1.1 riastrad 15 1.1 riastrad #include "intel_wakeref.h" 16 1.1 riastrad 17 1.1 riastrad #include "i915_utils.h" 18 1.1 riastrad 19 1.1 riastrad struct device; 20 1.1 riastrad struct drm_i915_private; 21 1.1 riastrad struct drm_printer; 22 1.1 riastrad 23 1.1 riastrad enum i915_drm_suspend_mode { 24 1.1 riastrad I915_DRM_SUSPEND_IDLE, 25 1.1 riastrad I915_DRM_SUSPEND_MEM, 26 1.1 riastrad I915_DRM_SUSPEND_HIBERNATE, 27 1.1 riastrad }; 28 1.1 riastrad 29 1.1 riastrad /* 30 1.1 riastrad * This struct helps tracking the state needed for runtime PM, which puts the 31 1.1 riastrad * device in PCI D3 state. Notice that when this happens, nothing on the 32 1.1 riastrad * graphics device works, even register access, so we don't get interrupts nor 33 1.1 riastrad * anything else. 34 1.1 riastrad * 35 1.1 riastrad * Every piece of our code that needs to actually touch the hardware needs to 36 1.1 riastrad * either call intel_runtime_pm_get or call intel_display_power_get with the 37 1.1 riastrad * appropriate power domain. 38 1.1 riastrad * 39 1.1 riastrad * Our driver uses the autosuspend delay feature, which means we'll only really 40 1.1 riastrad * suspend if we stay with zero refcount for a certain amount of time. The 41 1.1 riastrad * default value is currently very conservative (see intel_runtime_pm_enable), but 42 1.1 riastrad * it can be changed with the standard runtime PM files from sysfs. 43 1.1 riastrad * 44 1.1 riastrad * The irqs_disabled variable becomes true exactly after we disable the IRQs and 45 1.1 riastrad * goes back to false exactly before we reenable the IRQs. We use this variable 46 1.1 riastrad * to check if someone is trying to enable/disable IRQs while they're supposed 47 1.1 riastrad * to be disabled. This shouldn't happen and we'll print some error messages in 48 1.1 riastrad * case it happens. 49 1.1 riastrad * 50 1.1 riastrad * For more, read the Documentation/power/runtime_pm.rst. 51 1.1 riastrad */ 52 1.1 riastrad struct intel_runtime_pm { 53 1.1 riastrad atomic_t wakeref_count; 54 1.1 riastrad struct device *kdev; /* points to i915->drm.pdev->dev */ 55 1.1 riastrad bool available; 56 1.1 riastrad bool suspended; 57 1.1 riastrad bool irqs_enabled; 58 1.1 riastrad 59 1.1 riastrad #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) 60 1.1 riastrad /* 61 1.1 riastrad * To aide detection of wakeref leaks and general misuse, we 62 1.1 riastrad * track all wakeref holders. With manual markup (i.e. returning 63 1.1 riastrad * a cookie to each rpm_get caller which they then supply to their 64 1.1 riastrad * paired rpm_put) we can remove corresponding pairs of and keep 65 1.1 riastrad * the array trimmed to active wakerefs. 66 1.1 riastrad */ 67 1.1 riastrad struct intel_runtime_pm_debug { 68 1.1 riastrad spinlock_t lock; 69 1.1 riastrad 70 1.1 riastrad depot_stack_handle_t last_acquire; 71 1.1 riastrad depot_stack_handle_t last_release; 72 1.1 riastrad 73 1.1 riastrad depot_stack_handle_t *owners; 74 1.1 riastrad unsigned long count; 75 1.1 riastrad } debug; 76 1.1 riastrad #endif 77 1.1 riastrad }; 78 1.1 riastrad 79 1.1 riastrad #define BITS_PER_WAKEREF \ 80 1.1 riastrad BITS_PER_TYPE(struct_member(struct intel_runtime_pm, wakeref_count)) 81 1.1 riastrad #define INTEL_RPM_WAKELOCK_SHIFT (BITS_PER_WAKEREF / 2) 82 1.1 riastrad #define INTEL_RPM_WAKELOCK_BIAS (1 << INTEL_RPM_WAKELOCK_SHIFT) 83 1.1 riastrad #define INTEL_RPM_RAW_WAKEREF_MASK (INTEL_RPM_WAKELOCK_BIAS - 1) 84 1.1 riastrad 85 1.1 riastrad static inline int 86 1.1 riastrad intel_rpm_raw_wakeref_count(int wakeref_count) 87 1.1 riastrad { 88 1.1 riastrad return wakeref_count & INTEL_RPM_RAW_WAKEREF_MASK; 89 1.1 riastrad } 90 1.1 riastrad 91 1.1 riastrad static inline int 92 1.1 riastrad intel_rpm_wakelock_count(int wakeref_count) 93 1.1 riastrad { 94 1.1 riastrad return wakeref_count >> INTEL_RPM_WAKELOCK_SHIFT; 95 1.1 riastrad } 96 1.1 riastrad 97 1.1 riastrad static inline void 98 1.1 riastrad assert_rpm_device_not_suspended(struct intel_runtime_pm *rpm) 99 1.1 riastrad { 100 1.1 riastrad WARN_ONCE(rpm->suspended, 101 1.1 riastrad "Device suspended during HW access\n"); 102 1.1 riastrad } 103 1.1 riastrad 104 1.1 riastrad static inline void 105 1.1 riastrad __assert_rpm_raw_wakeref_held(struct intel_runtime_pm *rpm, int wakeref_count) 106 1.1 riastrad { 107 1.1 riastrad assert_rpm_device_not_suspended(rpm); 108 1.1 riastrad WARN_ONCE(!intel_rpm_raw_wakeref_count(wakeref_count), 109 1.1 riastrad "RPM raw-wakeref not held\n"); 110 1.1 riastrad } 111 1.1 riastrad 112 1.1 riastrad static inline void 113 1.1 riastrad __assert_rpm_wakelock_held(struct intel_runtime_pm *rpm, int wakeref_count) 114 1.1 riastrad { 115 1.1 riastrad __assert_rpm_raw_wakeref_held(rpm, wakeref_count); 116 1.1 riastrad WARN_ONCE(!intel_rpm_wakelock_count(wakeref_count), 117 1.1 riastrad "RPM wakelock ref not held during HW access\n"); 118 1.1 riastrad } 119 1.1 riastrad 120 1.1 riastrad static inline void 121 1.1 riastrad assert_rpm_raw_wakeref_held(struct intel_runtime_pm *rpm) 122 1.1 riastrad { 123 1.1 riastrad __assert_rpm_raw_wakeref_held(rpm, atomic_read(&rpm->wakeref_count)); 124 1.1 riastrad } 125 1.1 riastrad 126 1.1 riastrad static inline void 127 1.1 riastrad assert_rpm_wakelock_held(struct intel_runtime_pm *rpm) 128 1.1 riastrad { 129 1.1 riastrad __assert_rpm_wakelock_held(rpm, atomic_read(&rpm->wakeref_count)); 130 1.1 riastrad } 131 1.1 riastrad 132 1.1 riastrad /** 133 1.1 riastrad * disable_rpm_wakeref_asserts - disable the RPM assert checks 134 1.1 riastrad * @rpm: the intel_runtime_pm structure 135 1.1 riastrad * 136 1.1 riastrad * This function disable asserts that check if we hold an RPM wakelock 137 1.1 riastrad * reference, while keeping the device-not-suspended checks still enabled. 138 1.1 riastrad * It's meant to be used only in special circumstances where our rule about 139 1.1 riastrad * the wakelock refcount wrt. the device power state doesn't hold. According 140 1.1 riastrad * to this rule at any point where we access the HW or want to keep the HW in 141 1.1 riastrad * an active state we must hold an RPM wakelock reference acquired via one of 142 1.1 riastrad * the intel_runtime_pm_get() helpers. Currently there are a few special spots 143 1.1 riastrad * where this rule doesn't hold: the IRQ and suspend/resume handlers, the 144 1.1 riastrad * forcewake release timer, and the GPU RPS and hangcheck works. All other 145 1.1 riastrad * users should avoid using this function. 146 1.1 riastrad * 147 1.1 riastrad * Any calls to this function must have a symmetric call to 148 1.1 riastrad * enable_rpm_wakeref_asserts(). 149 1.1 riastrad */ 150 1.1 riastrad static inline void 151 1.1 riastrad disable_rpm_wakeref_asserts(struct intel_runtime_pm *rpm) 152 1.1 riastrad { 153 1.1 riastrad atomic_add(INTEL_RPM_WAKELOCK_BIAS + 1, 154 1.1 riastrad &rpm->wakeref_count); 155 1.1 riastrad } 156 1.1 riastrad 157 1.1 riastrad /** 158 1.1 riastrad * enable_rpm_wakeref_asserts - re-enable the RPM assert checks 159 1.1 riastrad * @rpm: the intel_runtime_pm structure 160 1.1 riastrad * 161 1.1 riastrad * This function re-enables the RPM assert checks after disabling them with 162 1.1 riastrad * disable_rpm_wakeref_asserts. It's meant to be used only in special 163 1.1 riastrad * circumstances otherwise its use should be avoided. 164 1.1 riastrad * 165 1.1 riastrad * Any calls to this function must have a symmetric call to 166 1.1 riastrad * disable_rpm_wakeref_asserts(). 167 1.1 riastrad */ 168 1.1 riastrad static inline void 169 1.1 riastrad enable_rpm_wakeref_asserts(struct intel_runtime_pm *rpm) 170 1.1 riastrad { 171 1.1 riastrad atomic_sub(INTEL_RPM_WAKELOCK_BIAS + 1, 172 1.1 riastrad &rpm->wakeref_count); 173 1.1 riastrad } 174 1.1 riastrad 175 1.1 riastrad void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm); 176 1.1 riastrad void intel_runtime_pm_enable(struct intel_runtime_pm *rpm); 177 1.1 riastrad void intel_runtime_pm_disable(struct intel_runtime_pm *rpm); 178 1.1 riastrad void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm); 179 1.1 riastrad 180 1.1 riastrad intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm); 181 1.1 riastrad intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm); 182 1.1 riastrad intel_wakeref_t intel_runtime_pm_get_noresume(struct intel_runtime_pm *rpm); 183 1.1 riastrad intel_wakeref_t intel_runtime_pm_get_raw(struct intel_runtime_pm *rpm); 184 1.1 riastrad 185 1.1 riastrad #define with_intel_runtime_pm(rpm, wf) \ 186 1.1 riastrad for ((wf) = intel_runtime_pm_get(rpm); (wf); \ 187 1.1 riastrad intel_runtime_pm_put((rpm), (wf)), (wf) = 0) 188 1.1 riastrad 189 1.1 riastrad #define with_intel_runtime_pm_if_in_use(rpm, wf) \ 190 1.1 riastrad for ((wf) = intel_runtime_pm_get_if_in_use(rpm); (wf); \ 191 1.1 riastrad intel_runtime_pm_put((rpm), (wf)), (wf) = 0) 192 1.1 riastrad 193 1.1 riastrad void intel_runtime_pm_put_unchecked(struct intel_runtime_pm *rpm); 194 1.1 riastrad #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) 195 1.1 riastrad void intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref); 196 1.1 riastrad #else 197 1.1 riastrad static inline void 198 1.1 riastrad intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref) 199 1.1 riastrad { 200 1.1 riastrad intel_runtime_pm_put_unchecked(rpm); 201 1.1 riastrad } 202 1.1 riastrad #endif 203 1.1 riastrad void intel_runtime_pm_put_raw(struct intel_runtime_pm *rpm, intel_wakeref_t wref); 204 1.1 riastrad 205 1.1 riastrad #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) 206 1.1 riastrad void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, 207 1.1 riastrad struct drm_printer *p); 208 1.1 riastrad #else 209 1.1 riastrad static inline void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, 210 1.1 riastrad struct drm_printer *p) 211 1.1 riastrad { 212 1.1 riastrad } 213 1.1 riastrad #endif 214 1.1 riastrad 215 1.1 riastrad #endif /* __INTEL_RUNTIME_PM_H__ */ 216