drivers/base/power/main.c

Source file repositories/reference/linux-study-clean/drivers/base/power/main.c

File Facts

System
Linux kernel
Corpus path
drivers/base/power/main.c
Extension
.c
Size
61986 bytes
Lines
2428
Domain
Driver Families
Bucket
drivers/base
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

subsys_initcall(dpm_watchdog_sysctl_init);

/**
 * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
 * @t: The timer that PM watchdog depends on.
 *
 * Called when a driver has timed out suspending or resuming.
 * There's not much we can do here to recover so panic() to
 * capture a crash-dump in pstore.
 */
static void dpm_watchdog_handler(struct timer_list *t)
{
	struct dpm_watchdog *wd = timer_container_of(wd, t, timer);
	struct timer_list *timer = &wd->timer;
	unsigned int time_left;

	if (wd->fatal) {
		unsigned int this_cpu = smp_processor_id();

		dev_emerg(wd->dev, "**** DPM device timeout ****\n");
		show_stack(wd->tsk, NULL, KERN_EMERG);
		if (dpm_watchdog_all_cpu_backtrace)
			trigger_allbutcpu_cpu_backtrace(this_cpu);
		panic("%s %s: unrecoverable failure\n",
			dev_driver_string(wd->dev), dev_name(wd->dev));
	}

	time_left = dpm_watchdog_timeout - dpm_watchdog_warning_timeout;
	dev_warn(wd->dev, "**** DPM device timeout after %u seconds; %u seconds until panic ****\n",
		 dpm_watchdog_warning_timeout, time_left);
	show_stack(wd->tsk, NULL, KERN_WARNING);

	wd->fatal = true;
	mod_timer(timer, jiffies + HZ * time_left);
}

/**
 * dpm_watchdog_set - Enable pm watchdog for given device.
 * @wd: Watchdog. Must be allocated on the stack.
 * @dev: Device to handle.
 */
static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
{
	struct timer_list *timer = &wd->timer;

	wd->dev = dev;
	wd->tsk = current;
	wd->fatal = dpm_watchdog_timeout == dpm_watchdog_warning_timeout;

	timer_setup_on_stack(timer, dpm_watchdog_handler, 0);
	/* use same timeout value for both suspend and resume */
	timer->expires = jiffies + HZ * dpm_watchdog_warning_timeout;
	add_timer(timer);
}

/**
 * dpm_watchdog_clear - Disable suspend/resume watchdog.
 * @wd: Watchdog to disable.
 */
static void dpm_watchdog_clear(struct dpm_watchdog *wd)
{
	struct timer_list *timer = &wd->timer;

	timer_delete_sync(timer);
	timer_destroy_on_stack(timer);
}
#else
#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
#define dpm_watchdog_set(x, y)
#define dpm_watchdog_clear(x)
#endif

/*------------------------- Resume routines -------------------------*/

/**
 * dev_pm_skip_resume - System-wide device resume optimization check.
 * @dev: Target device.
 *
 * Return:
 * - %false if the transition under way is RESTORE.
 * - Return value of dev_pm_skip_suspend() if the transition under way is THAW.
 * - The logical negation of %power.must_resume otherwise (that is, when the
 *   transition under way is RESUME).
 */
bool dev_pm_skip_resume(struct device *dev)
{
	if (pm_transition.event == PM_EVENT_RESTORE)
		return false;

	if (pm_transition.event == PM_EVENT_THAW)

Annotation

Implementation Notes