cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

intel_runtime_pm.h (7248B)


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