linux/drivers/gpu/drm/i915/intel_runtime_pm.c

472 lines
15 KiB
C
Raw Permalink Normal View History

/*
* 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 <eugeni.dodonov@intel.com>
* Daniel Vetter <daniel.vetter@ffwll.ch>
*
*/
#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)
{
return container_of(rpm, struct drm_i915_private, runtime_pm);
}
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
static void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
{
if (!rpm->debug.class)
ref_tracker_dir_init(&rpm->debug, INTEL_REFTRACK_DEAD_COUNT,
"intel_runtime_pm");
}
static intel_wakeref_t
track_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
{
if (!rpm->available || rpm->no_wakeref_tracking)
return INTEL_WAKEREF_DEF;
return intel_ref_tracker_alloc(&rpm->debug);
}
static void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm,
intel_wakeref_t wakeref)
{
if (!rpm->available || rpm->no_wakeref_tracking)
return;
intel_ref_tracker_free(&rpm->debug, wakeref);
}
static void untrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm)
{
ref_tracker_dir_exit(&rpm->debug);
}
static noinline void
__intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm)
{
unsigned long flags;
if (!atomic_dec_and_lock_irqsave(&rpm->wakeref_count,
&rpm->debug.lock,
flags))
return;
ref_tracker_dir_print_locked(&rpm->debug, INTEL_REFTRACK_PRINT_LIMIT);
spin_unlock_irqrestore(&rpm->debug.lock, flags);
}
void print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm,
struct drm_printer *p)
{
intel_ref_tracker_show(&rpm->debug, 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 INTEL_WAKEREF_DEF;
}
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)
{
if (wakelock) {
atomic_add(1 + INTEL_RPM_WAKELOCK_BIAS, &rpm->wakeref_count);
assert_rpm_wakelock_held(rpm);
} else {
atomic_inc(&rpm->wakeref_count);
assert_rpm_raw_wakeref_held(rpm);
}
}
static void
intel_runtime_pm_release(struct intel_runtime_pm *rpm, int wakelock)
{
if (wakelock) {
assert_rpm_wakelock_held(rpm);
atomic_sub(INTEL_RPM_WAKELOCK_BIAS, &rpm->wakeref_count);
} else {
assert_rpm_raw_wakeref_held(rpm);
}
__intel_wakeref_dec_and_check_tracking(rpm);
}
static intel_wakeref_t __intel_runtime_pm_get(struct intel_runtime_pm *rpm,
bool wakelock)
{
struct drm_i915_private *i915 = rpm_to_i915(rpm);
int ret;
ret = pm_runtime_get_sync(rpm->kdev);
drm_WARN_ONCE(&i915->drm, ret < 0,
"pm_runtime_get_sync() failed: %d\n", ret);
intel_runtime_pm_acquire(rpm, wakelock);
return track_intel_runtime_pm_wakeref(rpm);
}
/**
* 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)
{
return __intel_runtime_pm_get(rpm, false);
}
/**
* 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)
{
return __intel_runtime_pm_get(rpm, true);
}
/**
* __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)
{
if (IS_ENABLED(CONFIG_PM)) {
/*
* In cases runtime PM is disabled by the RPM core and we get
* an -EINVAL return value we are not supposed to call this
* function, since the power state is undefined. This applies
* atm to the late/early system suspend/resume handlers.
*/
if ((ignore_usecount &&
pm_runtime_get_if_active(rpm->kdev) <= 0) ||
(!ignore_usecount &&
pm_runtime_get_if_in_use(rpm->kdev) <= 0))
return NULL;
}
intel_runtime_pm_acquire(rpm, true);
return track_intel_runtime_pm_wakeref(rpm);
}
intel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm)
{
return __intel_runtime_pm_get_if_active(rpm, false);
}
intel_wakeref_t intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm)
{
return __intel_runtime_pm_get_if_active(rpm, true);
}
/**
* 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)
drm/i915/skl: Add DC5 Trigger Sequence Add triggers as per expectations mentioned in gen9_enable_dc5 and gen9_disable_dc5 patch. Also call POSTING_READ for every write to a register to ensure that its written immediately. v1: Remove POSTING_READ calls as they've already been added in previous patches. v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file. Modified as per review comments from Imre: 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant functions. 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into gen9_disable_DC5 which is a more appropriate place. 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well() to warnings. However, removing them for now as they'll be included in a future patch asserting DC-state entry/exit criteria. 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure to track 'enabled' and 'deferred' status of DC5. 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering runtime-suspend and release it when it's loaded. 6] Protect necessary CSR-related code with locks. 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be accessed during deferred DC5-enabling, are not initialized earlier. v3: Rebase to latest. Modified as per review comments from Imre: 1] Use blocking wait for CSR-loading to finish to enable DC5 for simplicity, instead of deferring enabling DC5 until CSR is loaded. 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5- enabling is removed and release it at the end of CSR-loading functionality. 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load functionality to avoid any delay in loading. 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling DC5 if it's true. 5] Define CSR-load-status accessor functions for use later. v4: 1] Disable DC5 before enabling PG2 instead of after it. 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that. 3] Enable DC5-related functionality using a macro. 4] Remove dc5_enabled tracking variable and its use as it's not needed now. v5: 1] Mark CSR failed to load where necessary in finish_csr_load function. 2] Use mutex-protected accessor function to check if CSR loaded instead of directly accessing the variable. 3] Prefix csr_load_status_get/set function names with intel_. v6: rebase to latest. v7: Rebase on top of nightly (Damien) v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre) v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v10: Added a enum for different csr states, suggested by Imre. (Animesh) v11: Based on review comments from Imre, Damien and Daniel following changes done - enum name chnaged to csr_state (singular form). - FW_UNINITIALIZED used as zeroth element in enum csr_state. - Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool. v12: Based on review comment from Imre, introduced bool fw_loaded local to finish_csr_load() which helps calling once to set the csr status. The same flag used to fail RPM if find any issue during firmware loading. Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-17 19:46:16 +05:30
{
assert_rpm_raw_wakeref_held(rpm);
pm_runtime_get_noresume(rpm->kdev);
drm/i915/skl: Assert the requirements to enter or exit DC5. Warn if the conditions to enter or exit DC5 are not satisfied such as support for runtime PM, state of power well, CSR loading etc. v2: Removed camelcase in functions and variables. v3: Do some minimal check to assert if CSR program is not loaded. v4: 1] Used an appropriate function lookup_power_well() to identify power well, instead of using a magic number which can change in future. 2] Split the conditions further in assert_can_enable_DC5() and added more checks. 3] Removed all WARNs from assert_can_disable_DC5 as they were unnecessary and added two new ones. 4] Changed variable names as updated in earlier patches. v5: 1] Change lookup_power_well function to take an int power well id. 2] Define a new intel_display_power_well_is_enabled helper function to check whether a particular power well is enabled. 3] Use CSR-related mutex in assert_csr_loaded function. v6: Remove use of dc5_enabled variable as it's no longer needed. v7: 1] Rebase to latest. 2] Move all DC5-related functions from intel_display.c to intel_runtime_pm.c. v8: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v9: Modified below changes based on review comments from Imre. - Moved intel_display_power_well_is_enabled() to intel_runtime_pm.c. - Removed mutex lock from assert_csr_loaded(). (Animesh) Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-16 14:22:10 +05:30
intel_runtime_pm_acquire(rpm, true);
drm/i915/skl: Assert the requirements to enter or exit DC5. Warn if the conditions to enter or exit DC5 are not satisfied such as support for runtime PM, state of power well, CSR loading etc. v2: Removed camelcase in functions and variables. v3: Do some minimal check to assert if CSR program is not loaded. v4: 1] Used an appropriate function lookup_power_well() to identify power well, instead of using a magic number which can change in future. 2] Split the conditions further in assert_can_enable_DC5() and added more checks. 3] Removed all WARNs from assert_can_disable_DC5 as they were unnecessary and added two new ones. 4] Changed variable names as updated in earlier patches. v5: 1] Change lookup_power_well function to take an int power well id. 2] Define a new intel_display_power_well_is_enabled helper function to check whether a particular power well is enabled. 3] Use CSR-related mutex in assert_csr_loaded function. v6: Remove use of dc5_enabled variable as it's no longer needed. v7: 1] Rebase to latest. 2] Move all DC5-related functions from intel_display.c to intel_runtime_pm.c. v8: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v9: Modified below changes based on review comments from Imre. - Moved intel_display_power_well_is_enabled() to intel_runtime_pm.c. - Removed mutex lock from assert_csr_loaded(). (Animesh) Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-16 14:22:10 +05:30
return track_intel_runtime_pm_wakeref(rpm);
drm/i915/skl: Assert the requirements to enter or exit DC5. Warn if the conditions to enter or exit DC5 are not satisfied such as support for runtime PM, state of power well, CSR loading etc. v2: Removed camelcase in functions and variables. v3: Do some minimal check to assert if CSR program is not loaded. v4: 1] Used an appropriate function lookup_power_well() to identify power well, instead of using a magic number which can change in future. 2] Split the conditions further in assert_can_enable_DC5() and added more checks. 3] Removed all WARNs from assert_can_disable_DC5 as they were unnecessary and added two new ones. 4] Changed variable names as updated in earlier patches. v5: 1] Change lookup_power_well function to take an int power well id. 2] Define a new intel_display_power_well_is_enabled helper function to check whether a particular power well is enabled. 3] Use CSR-related mutex in assert_csr_loaded function. v6: Remove use of dc5_enabled variable as it's no longer needed. v7: 1] Rebase to latest. 2] Move all DC5-related functions from intel_display.c to intel_runtime_pm.c. v8: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v9: Modified below changes based on review comments from Imre. - Moved intel_display_power_well_is_enabled() to intel_runtime_pm.c. - Removed mutex lock from assert_csr_loaded(). (Animesh) Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-16 14:22:10 +05:30
}
static void __intel_runtime_pm_put(struct intel_runtime_pm *rpm,
intel_wakeref_t wref,
bool wakelock)
drm/i915/skl: Assert the requirements to enter or exit DC5. Warn if the conditions to enter or exit DC5 are not satisfied such as support for runtime PM, state of power well, CSR loading etc. v2: Removed camelcase in functions and variables. v3: Do some minimal check to assert if CSR program is not loaded. v4: 1] Used an appropriate function lookup_power_well() to identify power well, instead of using a magic number which can change in future. 2] Split the conditions further in assert_can_enable_DC5() and added more checks. 3] Removed all WARNs from assert_can_disable_DC5 as they were unnecessary and added two new ones. 4] Changed variable names as updated in earlier patches. v5: 1] Change lookup_power_well function to take an int power well id. 2] Define a new intel_display_power_well_is_enabled helper function to check whether a particular power well is enabled. 3] Use CSR-related mutex in assert_csr_loaded function. v6: Remove use of dc5_enabled variable as it's no longer needed. v7: 1] Rebase to latest. 2] Move all DC5-related functions from intel_display.c to intel_runtime_pm.c. v8: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v9: Modified below changes based on review comments from Imre. - Moved intel_display_power_well_is_enabled() to intel_runtime_pm.c. - Removed mutex lock from assert_csr_loaded(). (Animesh) Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-16 14:22:10 +05:30
{
struct device *kdev = rpm->kdev;
untrack_intel_runtime_pm_wakeref(rpm, wref);
drm/i915/skl: Add DC5 Trigger Sequence Add triggers as per expectations mentioned in gen9_enable_dc5 and gen9_disable_dc5 patch. Also call POSTING_READ for every write to a register to ensure that its written immediately. v1: Remove POSTING_READ calls as they've already been added in previous patches. v2: Rebase to move all runtime pm specific changes to intel_runtime_pm.c file. Modified as per review comments from Imre: 1] Change variable name 'dc5_allowed' to 'dc5_enabled' to correspond to relevant functions. 2] Move the check dc5_enabled in skl_set_power_well() to disable DC5 into gen9_disable_DC5 which is a more appropriate place. 3] Convert checks for 'pm.dc5_enabled' and 'pm.suspended' in skl_set_power_well() to warnings. However, removing them for now as they'll be included in a future patch asserting DC-state entry/exit criteria. 4] Enable DC5, only when CSR firmware is verified to be loaded. Create new structure to track 'enabled' and 'deferred' status of DC5. 5] Ensure runtime PM reference is obtained, if CSR is not loaded, to avoid entering runtime-suspend and release it when it's loaded. 6] Protect necessary CSR-related code with locks. 7] Move CSR-loading call to runtime PM initialization, as power domains needed to be accessed during deferred DC5-enabling, are not initialized earlier. v3: Rebase to latest. Modified as per review comments from Imre: 1] Use blocking wait for CSR-loading to finish to enable DC5 for simplicity, instead of deferring enabling DC5 until CSR is loaded. 2] Obtain runtime PM reference during CSR-loading initialization itself as deferred DC5- enabling is removed and release it at the end of CSR-loading functionality. 3] Revert calling CSR-loading functionality to the beginning of i915 driver-load functionality to avoid any delay in loading. 4] Define another variable to track whether CSR-loading failed and use it to avoid enabling DC5 if it's true. 5] Define CSR-load-status accessor functions for use later. v4: 1] Disable DC5 before enabling PG2 instead of after it. 2] DC5 was being mistaken enabled even when CSR-loading timed-out. Fix that. 3] Enable DC5-related functionality using a macro. 4] Remove dc5_enabled tracking variable and its use as it's not needed now. v5: 1] Mark CSR failed to load where necessary in finish_csr_load function. 2] Use mutex-protected accessor function to check if CSR loaded instead of directly accessing the variable. 3] Prefix csr_load_status_get/set function names with intel_. v6: rebase to latest. v7: Rebase on top of nightly (Damien) v8: Squashed the patch from Imre - added csr helper pointers to simplify the code. (Imre) v9: After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v10: Added a enum for different csr states, suggested by Imre. (Animesh) v11: Based on review comments from Imre, Damien and Daniel following changes done - enum name chnaged to csr_state (singular form). - FW_UNINITIALIZED used as zeroth element in enum csr_state. - Prototype changed for helper function(set/get csr status), using enum csr_state instead of bool. v12: Based on review comment from Imre, introduced bool fw_loaded local to finish_csr_load() which helps calling once to set the csr status. The same flag used to fail RPM if find any issue during firmware loading. Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-17 19:46:16 +05:30
intel_runtime_pm_release(rpm, wakelock);
2015-04-16 14:22:13 +05:30
pm_runtime_mark_last_busy(kdev);
pm_runtime_put_autosuspend(kdev);
2015-04-16 14:22:13 +05:30
}
/**
* 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)
2015-04-16 14:22:13 +05:30
{
__intel_runtime_pm_put(rpm, wref, false);
drm/i915/skl: Add DC6 Trigger sequence. Add triggers for DC6 as per details provided in skl_enable_dc6 and skl_disable_dc6 implementations. Also Call POSTING_READ for every write to a register to ensure it is written to immediately v1: Remove POSTING_READ and intel_prepare_ddi calls as they've been added in previous patches. v2: 1] Remove check for backlight disabled as it should be the case by that time. 2] Mark DC5 as disabled when enabling DC6. 3] Return from DC5-disabling function early if DC5 is already be disabled which can happen due to DC6-enabling earlier. 3] Ensure CSR firmware is loaded after resume from DC6 as corresponding memory contents won't be retained after runtime-suspend. 4] Ensure that CSR isn't identified as loaded before CSR-loading program is called during runtime-resume. v3: Rebase to latest Modified as per review comments from Imre and after discussion with Art: 1] DC6 should be preferably enabled when PG2 is disabled by SW as the check for PG1 being disabled is taken of by HW to enter DC6, and disabled when PG2 is enabled respectively. This helps save more power, especially in the case when display is disabled but GT is enabled. Accordingly, replacing DC5 trigger sequence with DC6 for SKL. 2] DC6 could be enabled from intel_runtime_suspend() function, if DC5 is already enabled. 3] Move CSR-load-status setting code from intel_runtime_suspend function to a new function. v4: 1] Enable/disable DC6 only when toggling the power-well using a newly defined macro ENABLE_DC6. v5: 1] Load CSR on system resume too as firmware may be lost on system suspend preventing enabling DC5, DC6. 2] DDI buffers shouldn't be programmed during driver-load/resume as it's already done during modeset initialization then and also that the encoder list is still uninitialized by then. Therefore, call intel_prepare_ddi function right after disabling DC6 but outside skl_disable_dc6 function and not during driver-load/resume. v6: 1] Rebase to latest. 2] Move SKL_ENABLE_DC6 macro definition from intel_display.c to intel_runtime_pm.c. v7: 1) Refactored the code for removing the warning got from checkpatch. 2) After adding dmc ver 1.0 support rebased on top of nightly. (Animesh) v8: - Reverted the changes done in v7. - Removed the condition check in skl_prepare_resune(). (Animesh) Issue: VIZ-2819 Signed-off-by: A.Sunil Kamath <sunil.kamath@intel.com> Signed-off-by: Suketu Shah <suketu.j.shah@intel.com> Signed-off-by: Damien Lespiau <damien.lespiau@intel.com> Signed-off-by: Animesh Manna <animesh.manna@intel.com> Reviewed-by: Imre Deak <imre.deak@intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
2015-04-16 14:22:11 +05:30
}
/**
* 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)
{
__intel_runtime_pm_put(rpm, INTEL_WAKEREF_DEF, true);
}
#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)
{
__intel_runtime_pm_put(rpm, wref, true);
}
#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)
{
struct drm_i915_private *i915 = rpm_to_i915(rpm);
struct device *kdev = rpm->kdev;
/*
* Disable the system suspend direct complete optimization, which can
* leave the device suspended skipping the driver's suspend handlers
* if the device was already runtime suspended. This is needed due to
* the difference in our runtime and system suspend sequence and
* because the HDA driver may require us to enable the audio power
* domain during system suspend.
*/
dev_pm_set_driver_flags(kdev, DPM_FLAG_NO_DIRECT_COMPLETE);
pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */
pm_runtime_mark_last_busy(kdev);
/*
* Take a permanent reference to disable the RPM functionality and drop
* it only when unloading the driver. Use the low level get/put helpers,
* so the driver's own RPM reference tracking asserts also work on
* platforms without RPM support.
*/
if (!rpm->available) {
int ret;
pm_runtime_dont_use_autosuspend(kdev);
ret = pm_runtime_get_sync(kdev);
drm_WARN(&i915->drm, ret < 0,
"pm_runtime_get_sync() failed: %d\n", ret);
} else {
pm_runtime_use_autosuspend(kdev);
}
drm/i915/dgfx: Keep PCI autosuspend control 'on' by default on all dGPU DGFX platforms has lmem and cpu can access the lmem objects via mmap and i915 internal i915_gem_object_pin_map() for i915 own usages. Both of these methods has pre-requisite requirement to keep GFX PCI endpoint in D0 for a supported iomem transaction over PCI link. (Refer PCIe specs 5.3.1.4.1) Both DG1/DG2 have a known hardware bug that violates the PCIe specs and support the iomem read write transaction over PCIe bus despite endpoint is D3 state. Due to above H/W bug, we had never observed any issue with i915 runtime PM versus lmem access. But this issue becomes visible when PCIe gfx endpoint's upstream bridge enters to D3, at this point any lmem read/write access will be returned as unsupported request. But again this issue is not observed on every platform because it has been observed on few host machines DG1/DG2 endpoint's upstream bridge does not bind with pcieport driver. which really disables the PCIe power savings and leaves the bridge at D0 state. We need a unique interface to read/write from lmem with runtime PM wakeref protection something similar to intel_uncore_{read, write}, keep autosuspend control to 'on' on all discrete platforms, until we have a unique interface to read/write from lmem. This just change the default autosuspend setting of i915 on dGPU, user can still change it to 'auto'. v2: - Modified the commit message and subject with more information. - Changed the Fixes tag to LMEM support commit. [Joonas] - Changed !HAS_LMEM() Cond to !IS_DGFX(). [Rodrigo] Fixes: b908be543e44 ("drm/i915: support creating LMEM objects") Suggested-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Reviewed-by: Rodrigo Vivi <rodrigo.vivi@intel.com> Signed-off-by: Anshuman Gupta <anshuman.gupta@intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/20221014113258.1284226-1-anshuman.gupta@intel.com
2022-10-14 17:02:58 +05:30
/*
* FIXME: Temp hammer to keep autosupend disable on lmem supported platforms.
* As per PCIe specs 5.3.1.4.1, all iomem read write request over a PCIe
* function will be unsupported in case PCIe endpoint function is in D3.
* Let's keep i915 autosuspend control 'on' till we fix all known issue
* with lmem access in D3.
*/
if (!IS_DGFX(i915))
pm_runtime_allow(kdev);
/*
* The core calls the driver load handler with an RPM reference held.
* We drop that here and will reacquire it during unloading in
* intel_power_domains_fini().
*/
pm_runtime_put_autosuspend(kdev);
}
void intel_runtime_pm_disable(struct intel_runtime_pm *rpm)
{
struct drm_i915_private *i915 = rpm_to_i915(rpm);
struct device *kdev = rpm->kdev;
/* Transfer rpm ownership back to core */
drm_WARN(&i915->drm, pm_runtime_get_sync(kdev) < 0,
"Failed to pass rpm ownership back to core\n");
pm_runtime_dont_use_autosuspend(kdev);
if (!rpm->available)
pm_runtime_put(kdev);
}
void intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm)
{
struct drm_i915_private *i915 = rpm_to_i915(rpm);
int count = atomic_read(&rpm->wakeref_count);
intel_wakeref_auto_fini(&rpm->userfault_wakeref);
drm_WARN(&i915->drm, count,
"i915 raw-wakerefs=%d wakelocks=%d on cleanup\n",
intel_rpm_raw_wakeref_count(count),
intel_rpm_wakelock_count(count));
}
void intel_runtime_pm_driver_last_release(struct intel_runtime_pm *rpm)
{
intel_runtime_pm_driver_release(rpm);
untrack_all_intel_runtime_pm_wakerefs(rpm);
}
void intel_runtime_pm_init_early(struct intel_runtime_pm *rpm)
{
struct drm_i915_private *i915 = rpm_to_i915(rpm);
struct pci_dev *pdev = to_pci_dev(i915->drm.dev);
struct device *kdev = &pdev->dev;
rpm->kdev = kdev;
rpm->available = HAS_RUNTIME_PM(i915);
atomic_set(&rpm->wakeref_count, 0);
init_intel_runtime_pm_wakeref(rpm);
INIT_LIST_HEAD(&rpm->lmem_userfault_list);
spin_lock_init(&rpm->lmem_userfault_lock);
intel_wakeref_auto_init(&rpm->userfault_wakeref, i915);
}