static int __device_suspend_noirq()

in power/main.c [1199:1268]


static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
{
	pm_callback_t callback = NULL;
	const char *info = NULL;
	int error = 0;

	TRACE_DEVICE(dev);
	TRACE_SUSPEND(0);

	dpm_wait_for_subordinate(dev, async);

	if (async_error)
		goto Complete;

	if (dev->power.syscore || dev->power.direct_complete)
		goto Complete;

	if (dev->pm_domain) {
		info = "noirq power domain ";
		callback = pm_noirq_op(&dev->pm_domain->ops, state);
	} else if (dev->type && dev->type->pm) {
		info = "noirq type ";
		callback = pm_noirq_op(dev->type->pm, state);
	} else if (dev->class && dev->class->pm) {
		info = "noirq class ";
		callback = pm_noirq_op(dev->class->pm, state);
	} else if (dev->bus && dev->bus->pm) {
		info = "noirq bus ";
		callback = pm_noirq_op(dev->bus->pm, state);
	}
	if (callback)
		goto Run;

	if (dev_pm_skip_suspend(dev))
		goto Skip;

	if (dev->driver && dev->driver->pm) {
		info = "noirq driver ";
		callback = pm_noirq_op(dev->driver->pm, state);
	}

Run:
	error = dpm_run_callback(callback, dev, state, info);
	if (error) {
		async_error = error;
		goto Complete;
	}

Skip:
	dev->power.is_noirq_suspended = true;

	/*
	 * Skipping the resume of devices that were in use right before the
	 * system suspend (as indicated by their PM-runtime usage counters)
	 * would be suboptimal.  Also resume them if doing that is not allowed
	 * to be skipped.
	 */
	if (atomic_read(&dev->power.usage_count) > 1 ||
	    !(dev_pm_test_driver_flags(dev, DPM_FLAG_MAY_SKIP_RESUME) &&
	      dev->power.may_skip_resume))
		dev->power.must_resume = true;

	if (dev->power.must_resume)
		dpm_superior_set_must_resume(dev);

Complete:
	complete_all(&dev->power.completion);
	TRACE_SUSPEND(error);
	return error;
}