/* * Copyright © 2012-2014 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * * Authors: * Eugeni Dodonov <[email protected]> * Daniel Vetter <[email protected]> * */ #include <linux/pm_runtime.h> #include <drm/drm_print.h> #include "i915_drv.h" #include "i915_trace.h" /** * DOC: runtime pm * * The i915 driver supports dynamic enabling and disabling of entire hardware * blocks at runtime. This is especially important on the display side where * software is supposed to control many power gates manually on recent hardware, * since on the GT side a lot of the power management is done by the hardware. * But even there some manual control at the device level is required. * * Since i915 supports a diverse set of platforms with a unified codebase and * hardware engineers just love to shuffle functionality around between power * domains there's a sizeable amount of indirection required. This file provides * generic functions to the driver for grabbing and releasing references for * abstract power domains. It then maps those to the actual power wells * present for a given platform. */ static struct drm_i915_private *rpm_to_i915(struct intel_runtime_pm *rpm) { … } #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { … } static intel_wakeref_t track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { … } static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, intel_wakeref_t wakeref) { … } static void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) { … } static noinline void __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) { … } void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, struct drm_printer *p) { … } #else static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { } static intel_wakeref_t track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm) { return -1; } static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm, intel_wakeref_t wakeref) { } static void __intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm) { atomic_dec(&rpm->wakeref_count); } static void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm) { } #endif static void intel_runtime_pm_acquire(struct intel_runtime_pm *rpm, bool wakelock) { … } static void intel_runtime_pm_release(struct intel_runtime_pm *rpm, int wakelock) { … } static intel_wakeref_t __intel_runtime_pm_get(struct intel_runtime_pm *rpm, bool wakelock) { … } /** * intel_runtime_pm_get_raw - grab a raw runtime pm reference * @rpm: the intel_runtime_pm structure * * This is the unlocked version of intel_display_power_is_enabled() and should * only be used from error capture and recovery code where deadlocks are * possible. * This function grabs a device-level runtime pm reference (mostly used for * asynchronous PM management from display code) and ensures that it is powered * up. Raw references are not considered during wakelock assert checks. * * Any runtime pm reference obtained by this function must have a symmetric * call to intel_runtime_pm_put_raw() to release the reference again. * * Returns: the wakeref cookie to pass to intel_runtime_pm_put_raw(), evaluates * as True if the wakeref was acquired, or False otherwise. */ intel_wakeref_t intel_runtime_pm_get_raw(struct intel_runtime_pm *rpm) { … } /** * intel_runtime_pm_get - grab a runtime pm reference * @rpm: the intel_runtime_pm structure * * This function grabs a device-level runtime pm reference (mostly used for GEM * code to ensure the GTT or GT is on) and ensures that it is powered up. * * Any runtime pm reference obtained by this function must have a symmetric * call to intel_runtime_pm_put() to release the reference again. * * Returns: the wakeref cookie to pass to intel_runtime_pm_put() */ intel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm) { … } /** * __intel_runtime_pm_get_if_active - grab a runtime pm reference if device is active * @rpm: the intel_runtime_pm structure * @ignore_usecount: get a ref even if dev->power.usage_count is 0 * * This function grabs a device-level runtime pm reference if the device is * already active and ensures that it is powered up. It is illegal to try * and access the HW should intel_runtime_pm_get_if_active() report failure. * * If @ignore_usecount is true, a reference will be acquired even if there is no * user requiring the device to be powered up (dev->power.usage_count == 0). * If the function returns false in this case then it's guaranteed that the * device's runtime suspend hook has been called already or that it will be * called (and hence it's also guaranteed that the device's runtime resume * hook will be called eventually). * * Any runtime pm reference obtained by this function must have a symmetric * call to intel_runtime_pm_put() to release the reference again. * * Returns: the wakeref cookie to pass to intel_runtime_pm_put(), evaluates * as True if the wakeref was acquired, or False otherwise. */ static intel_wakeref_t __intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm, bool ignore_usecount) { … } intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm) { … } intel_wakeref_t intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm) { … } /** * intel_runtime_pm_get_noresume - grab a runtime pm reference * @rpm: the intel_runtime_pm structure * * This function grabs a device-level runtime pm reference. * * It will _not_ resume the device but instead only get an extra wakeref. * Therefore it is only valid to call this functions from contexts where * the device is known to be active and with another wakeref previously hold. * * Any runtime pm reference obtained by this function must have a symmetric * call to intel_runtime_pm_put() to release the reference again. * * Returns: the wakeref cookie to pass to intel_runtime_pm_put() */ intel_wakeref_t intel_runtime_pm_get_noresume(struct intel_runtime_pm *rpm) { … } static void __intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref, bool wakelock) { … } /** * intel_runtime_pm_put_raw - release a raw runtime pm reference * @rpm: the intel_runtime_pm structure * @wref: wakeref acquired for the reference that is being released * * This function drops the device-level runtime pm reference obtained by * intel_runtime_pm_get_raw() and might power down the corresponding * hardware block right away if this is the last reference. */ void intel_runtime_pm_put_raw(struct intel_runtime_pm *rpm, intel_wakeref_t wref) { … } /** * intel_runtime_pm_put_unchecked - release an unchecked runtime pm reference * @rpm: the intel_runtime_pm structure * * This function drops the device-level runtime pm reference obtained by * intel_runtime_pm_get() and might power down the corresponding * hardware block right away if this is the last reference. * * This function exists only for historical reasons and should be avoided in * new code, as the correctness of its use cannot be checked. Always use * intel_runtime_pm_put() instead. */ void intel_runtime_pm_put_unchecked(struct intel_runtime_pm *rpm) { … } #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) /** * intel_runtime_pm_put - release a runtime pm reference * @rpm: the intel_runtime_pm structure * @wref: wakeref acquired for the reference that is being released * * This function drops the device-level runtime pm reference obtained by * intel_runtime_pm_get() and might power down the corresponding * hardware block right away if this is the last reference. */ void intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref) { … } #endif /** * intel_runtime_pm_enable - enable runtime pm * @rpm: the intel_runtime_pm structure * * This function enables runtime pm at the end of the driver load sequence. * * Note that this function does currently not enable runtime pm for the * subordinate display power domains. That is done by * intel_power_domains_enable(). */ void intel_runtime_pm_enable(struct intel_runtime_pm *rpm) { … } void intel_runtime_pm_disable(struct intel_runtime_pm *rpm) { … } void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm) { … } void intel_runtime_pm_driver_last_release(struct intel_runtime_pm *rpm) { … } void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm) { … }