pm: don't suspend unready devices when entering low power states

The PM subsystem should not call the PM control callbacks on
uninitialized devices when entering low-power states.

Signed-off-by: Corey Wharton <xodus7@cwharton.com>
This commit is contained in:
Corey Wharton 2022-12-14 11:24:22 -08:00 committed by Fabio Baltieri
commit 21a7c2d7eb
3 changed files with 34 additions and 5 deletions

View file

@ -69,12 +69,13 @@ static int pm_suspend_devices(void)
int ret; int ret;
/* /*
* ignore busy devices, wake up source and devices with * Ignore uninitialized devices, busy devices, wake up sources, and
* runtime PM enabled. * devices with runtime PM enabled.
*/ */
if (pm_device_is_busy(dev) || pm_device_state_is_locked(dev) if (!device_is_ready(dev) || pm_device_is_busy(dev) ||
|| pm_device_wakeup_is_enabled(dev) || pm_device_state_is_locked(dev) ||
((dev->pm != NULL) && pm_device_runtime_is_enabled(dev))) { pm_device_wakeup_is_enabled(dev) ||
pm_device_runtime_is_enabled(dev)) {
continue; continue;
} }

View file

@ -16,4 +16,8 @@
device_c: device_c { device_c: device_c {
compatible = "test-device-pm"; compatible = "test-device-pm";
}; };
device_d: device_d {
compatible = "test-device-pm";
};
}; };

View file

@ -139,7 +139,31 @@ DEVICE_DT_DEFINE(DT_INST(2, test_device_pm), device_init,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
NULL); NULL);
static int device_init_failed(const struct device *dev)
{
ARG_UNUSED(dev);
/* Return error to mark device as not ready. */
return -EIO;
}
static int device_d_pm_action(const struct device *dev,
enum pm_device_action pm_action)
{
ARG_UNUSED(dev);
ARG_UNUSED(pm_action);
zassert_unreachable("Entered PM handler for unready device");
return 0;
}
PM_DEVICE_DT_DEFINE(DT_INST(3, test_device_pm), device_d_pm_action);
DEVICE_DT_DEFINE(DT_INST(3, test_device_pm), device_init_failed,
PM_DEVICE_DT_GET(DT_INST(3, test_device_pm)), NULL, NULL,
POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
NULL);
void pm_state_set(enum pm_state state, uint8_t substate_id) void pm_state_set(enum pm_state state, uint8_t substate_id)
{ {