Skip to content

Commit f7599be

Browse files
dtorrafaeljw
authored andcommitted
ACPI: PM: postpone bringing devices to D0 unless we need them
Currently ACPI power domain brings devices into D0 state in the "resume early" phase. Normally this does not cause any issues, as powering up happens quickly. However there are peripherals that have certain timing requirements for powering on, for example some models of Elan touchscreens need 300msec after powering up/releasing reset line before they can accept commands from the host. Such devices will dominate the time spent in early resume phase and cause increase in overall resume time as we wait for early resume to complete before we can proceed to the normal resume stage. There are ways for a driver to indicate that it can tolerate device being in the low power mode and that it knows how to power the device back up when resuming, bit that requires changes to individual drivers that may not really care about details of ACPI controlled power management. This change attempts to solve this issue at ACPI power domain level, by postponing powering up device until we get to the normal resume stage, unless there is early resume handler defined for the device, or device does not declare any resume handlers, in which case we continue powering up such devices early. This allows us to shave off several hundred milliseconds of resume time on affected systems. Signed-off-by: Dmitry Torokhov <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 8fbd6c1 commit f7599be

File tree

1 file changed

+31
-1
lines changed

1 file changed

+31
-1
lines changed

drivers/acpi/device_pm.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1134,19 +1134,48 @@ static int acpi_subsys_resume_noirq(struct device *dev)
11341134
*
11351135
* Use ACPI to put the given device into the full-power state and carry out the
11361136
* generic early resume procedure for it during system transition into the
1137-
* working state.
1137+
* working state, but only do that if device either defines early resume
1138+
* handler, or does not define power operations at all. Otherwise powering up
1139+
* of the device is postponed to the normal resume phase.
11381140
*/
11391141
static int acpi_subsys_resume_early(struct device *dev)
11401142
{
1143+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
11411144
int ret;
11421145

11431146
if (dev_pm_skip_resume(dev))
11441147
return 0;
11451148

1149+
if (pm && !pm->resume_early) {
1150+
dev_dbg(dev, "postponing D0 transition to normal resume stage\n");
1151+
return 0;
1152+
}
1153+
11461154
ret = acpi_dev_resume(dev);
11471155
return ret ? ret : pm_generic_resume_early(dev);
11481156
}
11491157

1158+
/**
1159+
* acpi_subsys_resume - Resume device using ACPI.
1160+
* @dev: Device to Resume.
1161+
*
1162+
* Use ACPI to put the given device into the full-power state if it has not been
1163+
* powered up during early resume phase, and carry out the generic resume
1164+
* procedure for it during system transition into the working state.
1165+
*/
1166+
static int acpi_subsys_resume(struct device *dev)
1167+
{
1168+
const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
1169+
int ret = 0;
1170+
1171+
if (!dev_pm_skip_resume(dev) && pm && !pm->resume_early) {
1172+
dev_dbg(dev, "executing postponed D0 transition\n");
1173+
ret = acpi_dev_resume(dev);
1174+
}
1175+
1176+
return ret ? ret : pm_generic_resume(dev);
1177+
}
1178+
11501179
/**
11511180
* acpi_subsys_freeze - Run the device driver's freeze callback.
11521181
* @dev: Device to handle.
@@ -1240,6 +1269,7 @@ static struct dev_pm_domain acpi_general_pm_domain = {
12401269
.prepare = acpi_subsys_prepare,
12411270
.complete = acpi_subsys_complete,
12421271
.suspend = acpi_subsys_suspend,
1272+
.resume = acpi_subsys_resume,
12431273
.suspend_late = acpi_subsys_suspend_late,
12441274
.suspend_noirq = acpi_subsys_suspend_noirq,
12451275
.resume_noirq = acpi_subsys_resume_noirq,

0 commit comments

Comments
 (0)