From 21a7c2d7eb645ae8dd8fb95abb56a5de0caeb01b Mon Sep 17 00:00:00 2001 From: Corey Wharton Date: Wed, 14 Dec 2022 11:24:22 -0800 Subject: [PATCH] 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 --- subsys/pm/pm.c | 11 +++++---- .../pm/power_mgmt/boards/native_posix.overlay | 4 ++++ tests/subsys/pm/power_mgmt/src/main.c | 24 +++++++++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/subsys/pm/pm.c b/subsys/pm/pm.c index 1b6e335ab9b..c4239a61fd5 100644 --- a/subsys/pm/pm.c +++ b/subsys/pm/pm.c @@ -69,12 +69,13 @@ static int pm_suspend_devices(void) int ret; /* - * ignore busy devices, wake up source and devices with - * runtime PM enabled. + * Ignore uninitialized devices, busy devices, wake up sources, and + * devices with runtime PM enabled. */ - if (pm_device_is_busy(dev) || pm_device_state_is_locked(dev) - || pm_device_wakeup_is_enabled(dev) || - ((dev->pm != NULL) && pm_device_runtime_is_enabled(dev))) { + if (!device_is_ready(dev) || pm_device_is_busy(dev) || + pm_device_state_is_locked(dev) || + pm_device_wakeup_is_enabled(dev) || + pm_device_runtime_is_enabled(dev)) { continue; } diff --git a/tests/subsys/pm/power_mgmt/boards/native_posix.overlay b/tests/subsys/pm/power_mgmt/boards/native_posix.overlay index 91013e67f35..8cd648a06e3 100644 --- a/tests/subsys/pm/power_mgmt/boards/native_posix.overlay +++ b/tests/subsys/pm/power_mgmt/boards/native_posix.overlay @@ -16,4 +16,8 @@ device_c: device_c { compatible = "test-device-pm"; }; + + device_d: device_d { + compatible = "test-device-pm"; + }; }; diff --git a/tests/subsys/pm/power_mgmt/src/main.c b/tests/subsys/pm/power_mgmt/src/main.c index f34ea8d629d..882b3100f34 100644 --- a/tests/subsys/pm/power_mgmt/src/main.c +++ b/tests/subsys/pm/power_mgmt/src/main.c @@ -139,7 +139,31 @@ DEVICE_DT_DEFINE(DT_INST(2, test_device_pm), device_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, 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) {