drivers/gpu/drm/i915/intel_runtime_pm.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/i915/intel_runtime_pm.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/i915/intel_runtime_pm.c
Extension
.c
Size
17386 bytes
Lines
549
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

#include <linux/pm_runtime.h>

#include <drm/drm_print.h>
#include <drm/intel/display_parent_interface.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)

Annotation

Implementation Notes