18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright © 2012-2014 Intel Corporation
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
58c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
68c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation
78c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
88c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
98c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice (including the next
128c2ecf20Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
138c2ecf20Sopenharmony_ci * Software.
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
178c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
188c2ecf20Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
198c2ecf20Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
208c2ecf20Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
218c2ecf20Sopenharmony_ci * IN THE SOFTWARE.
228c2ecf20Sopenharmony_ci *
238c2ecf20Sopenharmony_ci * Authors:
248c2ecf20Sopenharmony_ci *    Eugeni Dodonov <eugeni.dodonov@intel.com>
258c2ecf20Sopenharmony_ci *    Daniel Vetter <daniel.vetter@ffwll.ch>
268c2ecf20Sopenharmony_ci *
278c2ecf20Sopenharmony_ci */
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#include <drm/drm_print.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "i915_drv.h"
348c2ecf20Sopenharmony_ci#include "i915_trace.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/**
378c2ecf20Sopenharmony_ci * DOC: runtime pm
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci * The i915 driver supports dynamic enabling and disabling of entire hardware
408c2ecf20Sopenharmony_ci * blocks at runtime. This is especially important on the display side where
418c2ecf20Sopenharmony_ci * software is supposed to control many power gates manually on recent hardware,
428c2ecf20Sopenharmony_ci * since on the GT side a lot of the power management is done by the hardware.
438c2ecf20Sopenharmony_ci * But even there some manual control at the device level is required.
448c2ecf20Sopenharmony_ci *
458c2ecf20Sopenharmony_ci * Since i915 supports a diverse set of platforms with a unified codebase and
468c2ecf20Sopenharmony_ci * hardware engineers just love to shuffle functionality around between power
478c2ecf20Sopenharmony_ci * domains there's a sizeable amount of indirection required. This file provides
488c2ecf20Sopenharmony_ci * generic functions to the driver for grabbing and releasing references for
498c2ecf20Sopenharmony_ci * abstract power domains. It then maps those to the actual power wells
508c2ecf20Sopenharmony_ci * present for a given platform.
518c2ecf20Sopenharmony_ci */
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#include <linux/sort.h>
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci#define STACKDEPTH 8
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic noinline depot_stack_handle_t __save_depot_stack(void)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	unsigned long entries[STACKDEPTH];
628c2ecf20Sopenharmony_ci	unsigned int n;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	n = stack_trace_save(entries, ARRAY_SIZE(entries), 1);
658c2ecf20Sopenharmony_ci	return stack_depot_save(entries, n, GFP_NOWAIT | __GFP_NOWARN);
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic void __print_depot_stack(depot_stack_handle_t stack,
698c2ecf20Sopenharmony_ci				char *buf, int sz, int indent)
708c2ecf20Sopenharmony_ci{
718c2ecf20Sopenharmony_ci	unsigned long *entries;
728c2ecf20Sopenharmony_ci	unsigned int nr_entries;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	nr_entries = stack_depot_fetch(stack, &entries);
758c2ecf20Sopenharmony_ci	stack_trace_snprint(buf, sz, entries, nr_entries, indent);
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
798c2ecf20Sopenharmony_ci{
808c2ecf20Sopenharmony_ci	spin_lock_init(&rpm->debug.lock);
818c2ecf20Sopenharmony_ci}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_cistatic noinline depot_stack_handle_t
848c2ecf20Sopenharmony_citrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
858c2ecf20Sopenharmony_ci{
868c2ecf20Sopenharmony_ci	depot_stack_handle_t stack, *stacks;
878c2ecf20Sopenharmony_ci	unsigned long flags;
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	if (!rpm->available)
908c2ecf20Sopenharmony_ci		return -1;
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	stack = __save_depot_stack();
938c2ecf20Sopenharmony_ci	if (!stack)
948c2ecf20Sopenharmony_ci		return -1;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci	spin_lock_irqsave(&rpm->debug.lock, flags);
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	if (!rpm->debug.count)
998c2ecf20Sopenharmony_ci		rpm->debug.last_acquire = stack;
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	stacks = krealloc(rpm->debug.owners,
1028c2ecf20Sopenharmony_ci			  (rpm->debug.count + 1) * sizeof(*stacks),
1038c2ecf20Sopenharmony_ci			  GFP_NOWAIT | __GFP_NOWARN);
1048c2ecf20Sopenharmony_ci	if (stacks) {
1058c2ecf20Sopenharmony_ci		stacks[rpm->debug.count++] = stack;
1068c2ecf20Sopenharmony_ci		rpm->debug.owners = stacks;
1078c2ecf20Sopenharmony_ci	} else {
1088c2ecf20Sopenharmony_ci		stack = -1;
1098c2ecf20Sopenharmony_ci	}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rpm->debug.lock, flags);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	return stack;
1148c2ecf20Sopenharmony_ci}
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_cistatic void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm,
1178c2ecf20Sopenharmony_ci					     depot_stack_handle_t stack)
1188c2ecf20Sopenharmony_ci{
1198c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = container_of(rpm,
1208c2ecf20Sopenharmony_ci						     struct drm_i915_private,
1218c2ecf20Sopenharmony_ci						     runtime_pm);
1228c2ecf20Sopenharmony_ci	unsigned long flags, n;
1238c2ecf20Sopenharmony_ci	bool found = false;
1248c2ecf20Sopenharmony_ci
1258c2ecf20Sopenharmony_ci	if (unlikely(stack == -1))
1268c2ecf20Sopenharmony_ci		return;
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	spin_lock_irqsave(&rpm->debug.lock, flags);
1298c2ecf20Sopenharmony_ci	for (n = rpm->debug.count; n--; ) {
1308c2ecf20Sopenharmony_ci		if (rpm->debug.owners[n] == stack) {
1318c2ecf20Sopenharmony_ci			memmove(rpm->debug.owners + n,
1328c2ecf20Sopenharmony_ci				rpm->debug.owners + n + 1,
1338c2ecf20Sopenharmony_ci				(--rpm->debug.count - n) * sizeof(stack));
1348c2ecf20Sopenharmony_ci			found = true;
1358c2ecf20Sopenharmony_ci			break;
1368c2ecf20Sopenharmony_ci		}
1378c2ecf20Sopenharmony_ci	}
1388c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rpm->debug.lock, flags);
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	if (drm_WARN(&i915->drm, !found,
1418c2ecf20Sopenharmony_ci		     "Unmatched wakeref (tracking %lu), count %u\n",
1428c2ecf20Sopenharmony_ci		     rpm->debug.count, atomic_read(&rpm->wakeref_count))) {
1438c2ecf20Sopenharmony_ci		char *buf;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci		buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN);
1468c2ecf20Sopenharmony_ci		if (!buf)
1478c2ecf20Sopenharmony_ci			return;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci		__print_depot_stack(stack, buf, PAGE_SIZE, 2);
1508c2ecf20Sopenharmony_ci		DRM_DEBUG_DRIVER("wakeref %x from\n%s", stack, buf);
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci		stack = READ_ONCE(rpm->debug.last_release);
1538c2ecf20Sopenharmony_ci		if (stack) {
1548c2ecf20Sopenharmony_ci			__print_depot_stack(stack, buf, PAGE_SIZE, 2);
1558c2ecf20Sopenharmony_ci			DRM_DEBUG_DRIVER("wakeref last released at\n%s", buf);
1568c2ecf20Sopenharmony_ci		}
1578c2ecf20Sopenharmony_ci
1588c2ecf20Sopenharmony_ci		kfree(buf);
1598c2ecf20Sopenharmony_ci	}
1608c2ecf20Sopenharmony_ci}
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_cistatic int cmphandle(const void *_a, const void *_b)
1638c2ecf20Sopenharmony_ci{
1648c2ecf20Sopenharmony_ci	const depot_stack_handle_t * const a = _a, * const b = _b;
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_ci	if (*a < *b)
1678c2ecf20Sopenharmony_ci		return -1;
1688c2ecf20Sopenharmony_ci	else if (*a > *b)
1698c2ecf20Sopenharmony_ci		return 1;
1708c2ecf20Sopenharmony_ci	else
1718c2ecf20Sopenharmony_ci		return 0;
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic void
1758c2ecf20Sopenharmony_ci__print_intel_runtime_pm_wakeref(struct drm_printer *p,
1768c2ecf20Sopenharmony_ci				 const struct intel_runtime_pm_debug *dbg)
1778c2ecf20Sopenharmony_ci{
1788c2ecf20Sopenharmony_ci	unsigned long i;
1798c2ecf20Sopenharmony_ci	char *buf;
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci	buf = kmalloc(PAGE_SIZE, GFP_NOWAIT | __GFP_NOWARN);
1828c2ecf20Sopenharmony_ci	if (!buf)
1838c2ecf20Sopenharmony_ci		return;
1848c2ecf20Sopenharmony_ci
1858c2ecf20Sopenharmony_ci	if (dbg->last_acquire) {
1868c2ecf20Sopenharmony_ci		__print_depot_stack(dbg->last_acquire, buf, PAGE_SIZE, 2);
1878c2ecf20Sopenharmony_ci		drm_printf(p, "Wakeref last acquired:\n%s", buf);
1888c2ecf20Sopenharmony_ci	}
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (dbg->last_release) {
1918c2ecf20Sopenharmony_ci		__print_depot_stack(dbg->last_release, buf, PAGE_SIZE, 2);
1928c2ecf20Sopenharmony_ci		drm_printf(p, "Wakeref last released:\n%s", buf);
1938c2ecf20Sopenharmony_ci	}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci	drm_printf(p, "Wakeref count: %lu\n", dbg->count);
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	sort(dbg->owners, dbg->count, sizeof(*dbg->owners), cmphandle, NULL);
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	for (i = 0; i < dbg->count; i++) {
2008c2ecf20Sopenharmony_ci		depot_stack_handle_t stack = dbg->owners[i];
2018c2ecf20Sopenharmony_ci		unsigned long rep;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci		rep = 1;
2048c2ecf20Sopenharmony_ci		while (i + 1 < dbg->count && dbg->owners[i + 1] == stack)
2058c2ecf20Sopenharmony_ci			rep++, i++;
2068c2ecf20Sopenharmony_ci		__print_depot_stack(stack, buf, PAGE_SIZE, 2);
2078c2ecf20Sopenharmony_ci		drm_printf(p, "Wakeref x%lu taken at:\n%s", rep, buf);
2088c2ecf20Sopenharmony_ci	}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_ci	kfree(buf);
2118c2ecf20Sopenharmony_ci}
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_cistatic noinline void
2148c2ecf20Sopenharmony_ci__untrack_all_wakerefs(struct intel_runtime_pm_debug *debug,
2158c2ecf20Sopenharmony_ci		       struct intel_runtime_pm_debug *saved)
2168c2ecf20Sopenharmony_ci{
2178c2ecf20Sopenharmony_ci	*saved = *debug;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	debug->owners = NULL;
2208c2ecf20Sopenharmony_ci	debug->count = 0;
2218c2ecf20Sopenharmony_ci	debug->last_release = __save_depot_stack();
2228c2ecf20Sopenharmony_ci}
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_cistatic void
2258c2ecf20Sopenharmony_cidump_and_free_wakeref_tracking(struct intel_runtime_pm_debug *debug)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	if (debug->count) {
2288c2ecf20Sopenharmony_ci		struct drm_printer p = drm_debug_printer("i915");
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci		__print_intel_runtime_pm_wakeref(&p, debug);
2318c2ecf20Sopenharmony_ci	}
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci	kfree(debug->owners);
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic noinline void
2378c2ecf20Sopenharmony_ci__intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	struct intel_runtime_pm_debug dbg = {};
2408c2ecf20Sopenharmony_ci	unsigned long flags;
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	if (!atomic_dec_and_lock_irqsave(&rpm->wakeref_count,
2438c2ecf20Sopenharmony_ci					 &rpm->debug.lock,
2448c2ecf20Sopenharmony_ci					 flags))
2458c2ecf20Sopenharmony_ci		return;
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	__untrack_all_wakerefs(&rpm->debug, &dbg);
2488c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rpm->debug.lock, flags);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	dump_and_free_wakeref_tracking(&dbg);
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic noinline void
2548c2ecf20Sopenharmony_ciuntrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	struct intel_runtime_pm_debug dbg = {};
2578c2ecf20Sopenharmony_ci	unsigned long flags;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	spin_lock_irqsave(&rpm->debug.lock, flags);
2608c2ecf20Sopenharmony_ci	__untrack_all_wakerefs(&rpm->debug, &dbg);
2618c2ecf20Sopenharmony_ci	spin_unlock_irqrestore(&rpm->debug.lock, flags);
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	dump_and_free_wakeref_tracking(&dbg);
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_civoid print_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm,
2678c2ecf20Sopenharmony_ci				    struct drm_printer *p)
2688c2ecf20Sopenharmony_ci{
2698c2ecf20Sopenharmony_ci	struct intel_runtime_pm_debug dbg = {};
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	do {
2728c2ecf20Sopenharmony_ci		unsigned long alloc = dbg.count;
2738c2ecf20Sopenharmony_ci		depot_stack_handle_t *s;
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ci		spin_lock_irq(&rpm->debug.lock);
2768c2ecf20Sopenharmony_ci		dbg.count = rpm->debug.count;
2778c2ecf20Sopenharmony_ci		if (dbg.count <= alloc) {
2788c2ecf20Sopenharmony_ci			memcpy(dbg.owners,
2798c2ecf20Sopenharmony_ci			       rpm->debug.owners,
2808c2ecf20Sopenharmony_ci			       dbg.count * sizeof(*s));
2818c2ecf20Sopenharmony_ci		}
2828c2ecf20Sopenharmony_ci		dbg.last_acquire = rpm->debug.last_acquire;
2838c2ecf20Sopenharmony_ci		dbg.last_release = rpm->debug.last_release;
2848c2ecf20Sopenharmony_ci		spin_unlock_irq(&rpm->debug.lock);
2858c2ecf20Sopenharmony_ci		if (dbg.count <= alloc)
2868c2ecf20Sopenharmony_ci			break;
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci		s = krealloc(dbg.owners,
2898c2ecf20Sopenharmony_ci			     dbg.count * sizeof(*s),
2908c2ecf20Sopenharmony_ci			     GFP_NOWAIT | __GFP_NOWARN);
2918c2ecf20Sopenharmony_ci		if (!s)
2928c2ecf20Sopenharmony_ci			goto out;
2938c2ecf20Sopenharmony_ci
2948c2ecf20Sopenharmony_ci		dbg.owners = s;
2958c2ecf20Sopenharmony_ci	} while (1);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci	__print_intel_runtime_pm_wakeref(p, &dbg);
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ciout:
3008c2ecf20Sopenharmony_ci	kfree(dbg.owners);
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci#else
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_cistatic void init_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
3068c2ecf20Sopenharmony_ci{
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_cistatic depot_stack_handle_t
3108c2ecf20Sopenharmony_citrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm)
3118c2ecf20Sopenharmony_ci{
3128c2ecf20Sopenharmony_ci	return -1;
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic void untrack_intel_runtime_pm_wakeref(struct intel_runtime_pm *rpm,
3168c2ecf20Sopenharmony_ci					     intel_wakeref_t wref)
3178c2ecf20Sopenharmony_ci{
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_cistatic void
3218c2ecf20Sopenharmony_ci__intel_wakeref_dec_and_check_tracking(struct intel_runtime_pm *rpm)
3228c2ecf20Sopenharmony_ci{
3238c2ecf20Sopenharmony_ci	atomic_dec(&rpm->wakeref_count);
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ci
3268c2ecf20Sopenharmony_cistatic void
3278c2ecf20Sopenharmony_ciuntrack_all_intel_runtime_pm_wakerefs(struct intel_runtime_pm *rpm)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci}
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci#endif
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic void
3348c2ecf20Sopenharmony_ciintel_runtime_pm_acquire(struct intel_runtime_pm *rpm, bool wakelock)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	if (wakelock) {
3378c2ecf20Sopenharmony_ci		atomic_add(1 + INTEL_RPM_WAKELOCK_BIAS, &rpm->wakeref_count);
3388c2ecf20Sopenharmony_ci		assert_rpm_wakelock_held(rpm);
3398c2ecf20Sopenharmony_ci	} else {
3408c2ecf20Sopenharmony_ci		atomic_inc(&rpm->wakeref_count);
3418c2ecf20Sopenharmony_ci		assert_rpm_raw_wakeref_held(rpm);
3428c2ecf20Sopenharmony_ci	}
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic void
3468c2ecf20Sopenharmony_ciintel_runtime_pm_release(struct intel_runtime_pm *rpm, int wakelock)
3478c2ecf20Sopenharmony_ci{
3488c2ecf20Sopenharmony_ci	if (wakelock) {
3498c2ecf20Sopenharmony_ci		assert_rpm_wakelock_held(rpm);
3508c2ecf20Sopenharmony_ci		atomic_sub(INTEL_RPM_WAKELOCK_BIAS, &rpm->wakeref_count);
3518c2ecf20Sopenharmony_ci	} else {
3528c2ecf20Sopenharmony_ci		assert_rpm_raw_wakeref_held(rpm);
3538c2ecf20Sopenharmony_ci	}
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_ci	__intel_wakeref_dec_and_check_tracking(rpm);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic intel_wakeref_t __intel_runtime_pm_get(struct intel_runtime_pm *rpm,
3598c2ecf20Sopenharmony_ci					      bool wakelock)
3608c2ecf20Sopenharmony_ci{
3618c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = container_of(rpm,
3628c2ecf20Sopenharmony_ci						     struct drm_i915_private,
3638c2ecf20Sopenharmony_ci						     runtime_pm);
3648c2ecf20Sopenharmony_ci	int ret;
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	ret = pm_runtime_get_sync(rpm->kdev);
3678c2ecf20Sopenharmony_ci	drm_WARN_ONCE(&i915->drm, ret < 0,
3688c2ecf20Sopenharmony_ci		      "pm_runtime_get_sync() failed: %d\n", ret);
3698c2ecf20Sopenharmony_ci
3708c2ecf20Sopenharmony_ci	intel_runtime_pm_acquire(rpm, wakelock);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	return track_intel_runtime_pm_wakeref(rpm);
3738c2ecf20Sopenharmony_ci}
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci/**
3768c2ecf20Sopenharmony_ci * intel_runtime_pm_get_raw - grab a raw runtime pm reference
3778c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
3788c2ecf20Sopenharmony_ci *
3798c2ecf20Sopenharmony_ci * This is the unlocked version of intel_display_power_is_enabled() and should
3808c2ecf20Sopenharmony_ci * only be used from error capture and recovery code where deadlocks are
3818c2ecf20Sopenharmony_ci * possible.
3828c2ecf20Sopenharmony_ci * This function grabs a device-level runtime pm reference (mostly used for
3838c2ecf20Sopenharmony_ci * asynchronous PM management from display code) and ensures that it is powered
3848c2ecf20Sopenharmony_ci * up. Raw references are not considered during wakelock assert checks.
3858c2ecf20Sopenharmony_ci *
3868c2ecf20Sopenharmony_ci * Any runtime pm reference obtained by this function must have a symmetric
3878c2ecf20Sopenharmony_ci * call to intel_runtime_pm_put_raw() to release the reference again.
3888c2ecf20Sopenharmony_ci *
3898c2ecf20Sopenharmony_ci * Returns: the wakeref cookie to pass to intel_runtime_pm_put_raw(), evaluates
3908c2ecf20Sopenharmony_ci * as True if the wakeref was acquired, or False otherwise.
3918c2ecf20Sopenharmony_ci */
3928c2ecf20Sopenharmony_ciintel_wakeref_t intel_runtime_pm_get_raw(struct intel_runtime_pm *rpm)
3938c2ecf20Sopenharmony_ci{
3948c2ecf20Sopenharmony_ci	return __intel_runtime_pm_get(rpm, false);
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci/**
3988c2ecf20Sopenharmony_ci * intel_runtime_pm_get - grab a runtime pm reference
3998c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
4008c2ecf20Sopenharmony_ci *
4018c2ecf20Sopenharmony_ci * This function grabs a device-level runtime pm reference (mostly used for GEM
4028c2ecf20Sopenharmony_ci * code to ensure the GTT or GT is on) and ensures that it is powered up.
4038c2ecf20Sopenharmony_ci *
4048c2ecf20Sopenharmony_ci * Any runtime pm reference obtained by this function must have a symmetric
4058c2ecf20Sopenharmony_ci * call to intel_runtime_pm_put() to release the reference again.
4068c2ecf20Sopenharmony_ci *
4078c2ecf20Sopenharmony_ci * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
4088c2ecf20Sopenharmony_ci */
4098c2ecf20Sopenharmony_ciintel_wakeref_t intel_runtime_pm_get(struct intel_runtime_pm *rpm)
4108c2ecf20Sopenharmony_ci{
4118c2ecf20Sopenharmony_ci	return __intel_runtime_pm_get(rpm, true);
4128c2ecf20Sopenharmony_ci}
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci/**
4158c2ecf20Sopenharmony_ci * __intel_runtime_pm_get_if_active - grab a runtime pm reference if device is active
4168c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
4178c2ecf20Sopenharmony_ci * @ignore_usecount: get a ref even if dev->power.usage_count is 0
4188c2ecf20Sopenharmony_ci *
4198c2ecf20Sopenharmony_ci * This function grabs a device-level runtime pm reference if the device is
4208c2ecf20Sopenharmony_ci * already active and ensures that it is powered up. It is illegal to try
4218c2ecf20Sopenharmony_ci * and access the HW should intel_runtime_pm_get_if_active() report failure.
4228c2ecf20Sopenharmony_ci *
4238c2ecf20Sopenharmony_ci * If @ignore_usecount=true, a reference will be acquired even if there is no
4248c2ecf20Sopenharmony_ci * user requiring the device to be powered up (dev->power.usage_count == 0).
4258c2ecf20Sopenharmony_ci * If the function returns false in this case then it's guaranteed that the
4268c2ecf20Sopenharmony_ci * device's runtime suspend hook has been called already or that it will be
4278c2ecf20Sopenharmony_ci * called (and hence it's also guaranteed that the device's runtime resume
4288c2ecf20Sopenharmony_ci * hook will be called eventually).
4298c2ecf20Sopenharmony_ci *
4308c2ecf20Sopenharmony_ci * Any runtime pm reference obtained by this function must have a symmetric
4318c2ecf20Sopenharmony_ci * call to intel_runtime_pm_put() to release the reference again.
4328c2ecf20Sopenharmony_ci *
4338c2ecf20Sopenharmony_ci * Returns: the wakeref cookie to pass to intel_runtime_pm_put(), evaluates
4348c2ecf20Sopenharmony_ci * as True if the wakeref was acquired, or False otherwise.
4358c2ecf20Sopenharmony_ci */
4368c2ecf20Sopenharmony_cistatic intel_wakeref_t __intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm,
4378c2ecf20Sopenharmony_ci							bool ignore_usecount)
4388c2ecf20Sopenharmony_ci{
4398c2ecf20Sopenharmony_ci	if (IS_ENABLED(CONFIG_PM)) {
4408c2ecf20Sopenharmony_ci		/*
4418c2ecf20Sopenharmony_ci		 * In cases runtime PM is disabled by the RPM core and we get
4428c2ecf20Sopenharmony_ci		 * an -EINVAL return value we are not supposed to call this
4438c2ecf20Sopenharmony_ci		 * function, since the power state is undefined. This applies
4448c2ecf20Sopenharmony_ci		 * atm to the late/early system suspend/resume handlers.
4458c2ecf20Sopenharmony_ci		 */
4468c2ecf20Sopenharmony_ci		if (pm_runtime_get_if_active(rpm->kdev, ignore_usecount) <= 0)
4478c2ecf20Sopenharmony_ci			return 0;
4488c2ecf20Sopenharmony_ci	}
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	intel_runtime_pm_acquire(rpm, true);
4518c2ecf20Sopenharmony_ci
4528c2ecf20Sopenharmony_ci	return track_intel_runtime_pm_wakeref(rpm);
4538c2ecf20Sopenharmony_ci}
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ciintel_wakeref_t intel_runtime_pm_get_if_in_use(struct intel_runtime_pm *rpm)
4568c2ecf20Sopenharmony_ci{
4578c2ecf20Sopenharmony_ci	return __intel_runtime_pm_get_if_active(rpm, false);
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ciintel_wakeref_t intel_runtime_pm_get_if_active(struct intel_runtime_pm *rpm)
4618c2ecf20Sopenharmony_ci{
4628c2ecf20Sopenharmony_ci	return __intel_runtime_pm_get_if_active(rpm, true);
4638c2ecf20Sopenharmony_ci}
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci/**
4668c2ecf20Sopenharmony_ci * intel_runtime_pm_get_noresume - grab a runtime pm reference
4678c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
4688c2ecf20Sopenharmony_ci *
4698c2ecf20Sopenharmony_ci * This function grabs a device-level runtime pm reference (mostly used for GEM
4708c2ecf20Sopenharmony_ci * code to ensure the GTT or GT is on).
4718c2ecf20Sopenharmony_ci *
4728c2ecf20Sopenharmony_ci * It will _not_ power up the device but instead only check that it's powered
4738c2ecf20Sopenharmony_ci * on.  Therefore it is only valid to call this functions from contexts where
4748c2ecf20Sopenharmony_ci * the device is known to be powered up and where trying to power it up would
4758c2ecf20Sopenharmony_ci * result in hilarity and deadlocks. That pretty much means only the system
4768c2ecf20Sopenharmony_ci * suspend/resume code where this is used to grab runtime pm references for
4778c2ecf20Sopenharmony_ci * delayed setup down in work items.
4788c2ecf20Sopenharmony_ci *
4798c2ecf20Sopenharmony_ci * Any runtime pm reference obtained by this function must have a symmetric
4808c2ecf20Sopenharmony_ci * call to intel_runtime_pm_put() to release the reference again.
4818c2ecf20Sopenharmony_ci *
4828c2ecf20Sopenharmony_ci * Returns: the wakeref cookie to pass to intel_runtime_pm_put()
4838c2ecf20Sopenharmony_ci */
4848c2ecf20Sopenharmony_ciintel_wakeref_t intel_runtime_pm_get_noresume(struct intel_runtime_pm *rpm)
4858c2ecf20Sopenharmony_ci{
4868c2ecf20Sopenharmony_ci	assert_rpm_wakelock_held(rpm);
4878c2ecf20Sopenharmony_ci	pm_runtime_get_noresume(rpm->kdev);
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci	intel_runtime_pm_acquire(rpm, true);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	return track_intel_runtime_pm_wakeref(rpm);
4928c2ecf20Sopenharmony_ci}
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_cistatic void __intel_runtime_pm_put(struct intel_runtime_pm *rpm,
4958c2ecf20Sopenharmony_ci				   intel_wakeref_t wref,
4968c2ecf20Sopenharmony_ci				   bool wakelock)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct device *kdev = rpm->kdev;
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	untrack_intel_runtime_pm_wakeref(rpm, wref);
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	intel_runtime_pm_release(rpm, wakelock);
5038c2ecf20Sopenharmony_ci
5048c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(kdev);
5058c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(kdev);
5068c2ecf20Sopenharmony_ci}
5078c2ecf20Sopenharmony_ci
5088c2ecf20Sopenharmony_ci/**
5098c2ecf20Sopenharmony_ci * intel_runtime_pm_put_raw - release a raw runtime pm reference
5108c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
5118c2ecf20Sopenharmony_ci * @wref: wakeref acquired for the reference that is being released
5128c2ecf20Sopenharmony_ci *
5138c2ecf20Sopenharmony_ci * This function drops the device-level runtime pm reference obtained by
5148c2ecf20Sopenharmony_ci * intel_runtime_pm_get_raw() and might power down the corresponding
5158c2ecf20Sopenharmony_ci * hardware block right away if this is the last reference.
5168c2ecf20Sopenharmony_ci */
5178c2ecf20Sopenharmony_civoid
5188c2ecf20Sopenharmony_ciintel_runtime_pm_put_raw(struct intel_runtime_pm *rpm, intel_wakeref_t wref)
5198c2ecf20Sopenharmony_ci{
5208c2ecf20Sopenharmony_ci	__intel_runtime_pm_put(rpm, wref, false);
5218c2ecf20Sopenharmony_ci}
5228c2ecf20Sopenharmony_ci
5238c2ecf20Sopenharmony_ci/**
5248c2ecf20Sopenharmony_ci * intel_runtime_pm_put_unchecked - release an unchecked runtime pm reference
5258c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
5268c2ecf20Sopenharmony_ci *
5278c2ecf20Sopenharmony_ci * This function drops the device-level runtime pm reference obtained by
5288c2ecf20Sopenharmony_ci * intel_runtime_pm_get() and might power down the corresponding
5298c2ecf20Sopenharmony_ci * hardware block right away if this is the last reference.
5308c2ecf20Sopenharmony_ci *
5318c2ecf20Sopenharmony_ci * This function exists only for historical reasons and should be avoided in
5328c2ecf20Sopenharmony_ci * new code, as the correctness of its use cannot be checked. Always use
5338c2ecf20Sopenharmony_ci * intel_runtime_pm_put() instead.
5348c2ecf20Sopenharmony_ci */
5358c2ecf20Sopenharmony_civoid intel_runtime_pm_put_unchecked(struct intel_runtime_pm *rpm)
5368c2ecf20Sopenharmony_ci{
5378c2ecf20Sopenharmony_ci	__intel_runtime_pm_put(rpm, -1, true);
5388c2ecf20Sopenharmony_ci}
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
5418c2ecf20Sopenharmony_ci/**
5428c2ecf20Sopenharmony_ci * intel_runtime_pm_put - release a runtime pm reference
5438c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
5448c2ecf20Sopenharmony_ci * @wref: wakeref acquired for the reference that is being released
5458c2ecf20Sopenharmony_ci *
5468c2ecf20Sopenharmony_ci * This function drops the device-level runtime pm reference obtained by
5478c2ecf20Sopenharmony_ci * intel_runtime_pm_get() and might power down the corresponding
5488c2ecf20Sopenharmony_ci * hardware block right away if this is the last reference.
5498c2ecf20Sopenharmony_ci */
5508c2ecf20Sopenharmony_civoid intel_runtime_pm_put(struct intel_runtime_pm *rpm, intel_wakeref_t wref)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	__intel_runtime_pm_put(rpm, wref, true);
5538c2ecf20Sopenharmony_ci}
5548c2ecf20Sopenharmony_ci#endif
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci/**
5578c2ecf20Sopenharmony_ci * intel_runtime_pm_enable - enable runtime pm
5588c2ecf20Sopenharmony_ci * @rpm: the intel_runtime_pm structure
5598c2ecf20Sopenharmony_ci *
5608c2ecf20Sopenharmony_ci * This function enables runtime pm at the end of the driver load sequence.
5618c2ecf20Sopenharmony_ci *
5628c2ecf20Sopenharmony_ci * Note that this function does currently not enable runtime pm for the
5638c2ecf20Sopenharmony_ci * subordinate display power domains. That is done by
5648c2ecf20Sopenharmony_ci * intel_power_domains_enable().
5658c2ecf20Sopenharmony_ci */
5668c2ecf20Sopenharmony_civoid intel_runtime_pm_enable(struct intel_runtime_pm *rpm)
5678c2ecf20Sopenharmony_ci{
5688c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = container_of(rpm,
5698c2ecf20Sopenharmony_ci						     struct drm_i915_private,
5708c2ecf20Sopenharmony_ci						     runtime_pm);
5718c2ecf20Sopenharmony_ci	struct device *kdev = rpm->kdev;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	/*
5748c2ecf20Sopenharmony_ci	 * Disable the system suspend direct complete optimization, which can
5758c2ecf20Sopenharmony_ci	 * leave the device suspended skipping the driver's suspend handlers
5768c2ecf20Sopenharmony_ci	 * if the device was already runtime suspended. This is needed due to
5778c2ecf20Sopenharmony_ci	 * the difference in our runtime and system suspend sequence and
5788c2ecf20Sopenharmony_ci	 * becaue the HDA driver may require us to enable the audio power
5798c2ecf20Sopenharmony_ci	 * domain during system suspend.
5808c2ecf20Sopenharmony_ci	 */
5818c2ecf20Sopenharmony_ci	dev_pm_set_driver_flags(kdev, DPM_FLAG_NO_DIRECT_COMPLETE);
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_ci	pm_runtime_set_autosuspend_delay(kdev, 10000); /* 10s */
5848c2ecf20Sopenharmony_ci	pm_runtime_mark_last_busy(kdev);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	/*
5878c2ecf20Sopenharmony_ci	 * Take a permanent reference to disable the RPM functionality and drop
5888c2ecf20Sopenharmony_ci	 * it only when unloading the driver. Use the low level get/put helpers,
5898c2ecf20Sopenharmony_ci	 * so the driver's own RPM reference tracking asserts also work on
5908c2ecf20Sopenharmony_ci	 * platforms without RPM support.
5918c2ecf20Sopenharmony_ci	 */
5928c2ecf20Sopenharmony_ci	if (!rpm->available) {
5938c2ecf20Sopenharmony_ci		int ret;
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci		pm_runtime_dont_use_autosuspend(kdev);
5968c2ecf20Sopenharmony_ci		ret = pm_runtime_get_sync(kdev);
5978c2ecf20Sopenharmony_ci		drm_WARN(&i915->drm, ret < 0,
5988c2ecf20Sopenharmony_ci			 "pm_runtime_get_sync() failed: %d\n", ret);
5998c2ecf20Sopenharmony_ci	} else {
6008c2ecf20Sopenharmony_ci		pm_runtime_use_autosuspend(kdev);
6018c2ecf20Sopenharmony_ci	}
6028c2ecf20Sopenharmony_ci
6038c2ecf20Sopenharmony_ci	/*
6048c2ecf20Sopenharmony_ci	 * The core calls the driver load handler with an RPM reference held.
6058c2ecf20Sopenharmony_ci	 * We drop that here and will reacquire it during unloading in
6068c2ecf20Sopenharmony_ci	 * intel_power_domains_fini().
6078c2ecf20Sopenharmony_ci	 */
6088c2ecf20Sopenharmony_ci	pm_runtime_put_autosuspend(kdev);
6098c2ecf20Sopenharmony_ci}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_civoid intel_runtime_pm_disable(struct intel_runtime_pm *rpm)
6128c2ecf20Sopenharmony_ci{
6138c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = container_of(rpm,
6148c2ecf20Sopenharmony_ci						     struct drm_i915_private,
6158c2ecf20Sopenharmony_ci						     runtime_pm);
6168c2ecf20Sopenharmony_ci	struct device *kdev = rpm->kdev;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	/* Transfer rpm ownership back to core */
6198c2ecf20Sopenharmony_ci	drm_WARN(&i915->drm, pm_runtime_get_sync(kdev) < 0,
6208c2ecf20Sopenharmony_ci		 "Failed to pass rpm ownership back to core\n");
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	pm_runtime_dont_use_autosuspend(kdev);
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	if (!rpm->available)
6258c2ecf20Sopenharmony_ci		pm_runtime_put(kdev);
6268c2ecf20Sopenharmony_ci}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_civoid intel_runtime_pm_driver_release(struct intel_runtime_pm *rpm)
6298c2ecf20Sopenharmony_ci{
6308c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 = container_of(rpm,
6318c2ecf20Sopenharmony_ci						     struct drm_i915_private,
6328c2ecf20Sopenharmony_ci						     runtime_pm);
6338c2ecf20Sopenharmony_ci	int count = atomic_read(&rpm->wakeref_count);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	drm_WARN(&i915->drm, count,
6368c2ecf20Sopenharmony_ci		 "i915 raw-wakerefs=%d wakelocks=%d on cleanup\n",
6378c2ecf20Sopenharmony_ci		 intel_rpm_raw_wakeref_count(count),
6388c2ecf20Sopenharmony_ci		 intel_rpm_wakelock_count(count));
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci	untrack_all_intel_runtime_pm_wakerefs(rpm);
6418c2ecf20Sopenharmony_ci}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_civoid intel_runtime_pm_init_early(struct intel_runtime_pm *rpm)
6448c2ecf20Sopenharmony_ci{
6458c2ecf20Sopenharmony_ci	struct drm_i915_private *i915 =
6468c2ecf20Sopenharmony_ci			container_of(rpm, struct drm_i915_private, runtime_pm);
6478c2ecf20Sopenharmony_ci	struct pci_dev *pdev = i915->drm.pdev;
6488c2ecf20Sopenharmony_ci	struct device *kdev = &pdev->dev;
6498c2ecf20Sopenharmony_ci
6508c2ecf20Sopenharmony_ci	rpm->kdev = kdev;
6518c2ecf20Sopenharmony_ci	rpm->available = HAS_RUNTIME_PM(i915);
6528c2ecf20Sopenharmony_ci
6538c2ecf20Sopenharmony_ci	init_intel_runtime_pm_wakeref(rpm);
6548c2ecf20Sopenharmony_ci}
655