diff options
Diffstat (limited to 'kernel/kapi/devices/power.cpp')
| -rw-r--r-- | kernel/kapi/devices/power.cpp | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/kernel/kapi/devices/power.cpp b/kernel/kapi/devices/power.cpp new file mode 100644 index 00000000..3bc66848 --- /dev/null +++ b/kernel/kapi/devices/power.cpp @@ -0,0 +1,93 @@ +#include <kapi/devices/power.hpp> + +#include <kapi/devices.hpp> + +#include <kstd/memory.hpp> +#include <kstd/print.hpp> +#include <kstd/result.hpp> +#include <kstd/vector.hpp> + +#include <ranges> + +namespace kapi::devices +{ + + namespace + { + auto resume_subtree(device & node) -> void; + + // NOLINTNEXTLINE(misc-no-recursion) + auto suspend_subtree(device & node) -> kstd::result<void> + { + auto suspended_children = kstd::vector<kstd::shared_ptr<device>>{}; + + if (auto as_bus = node.facet<bus>()) + { + for (auto const & child : as_bus->children()) + { + auto result = suspend_subtree(*child); + if (!result) + { + for (auto const & already_suspended : std::views::reverse(suspended_children)) + { + resume_subtree(*already_suspended); + } + + return result; + } + + suspended_children.push_back(child); + } + } + + if (auto driver = node.bound_driver()) + { + auto result = driver->suspend(node); + if (!result) + { + for (auto const & already_suspended : std::views::reverse(suspended_children)) + { + resume_subtree(*already_suspended); + } + + return result; + } + } + + return kstd::success(); + } + + // NOLINTNEXTLINE(misc-no-recursion) + auto resume_subtree(device & node) -> void + { + if (auto driver = node.bound_driver()) + { + auto result = driver->resume(node); + if (!result) + { + kstd::println(kstd::print_sink::stderr, "[OS:PM] failed to resume device '{}': {}", node.name(), + result.error().message()); + } + } + + if (auto as_bus = node.facet<bus>()) + { + for (auto const & child : as_bus->children()) + { + resume_subtree(*child); + } + } + } + } // namespace + + auto suspend_tree(bus & root) -> kstd::result<void> + { + return suspend_subtree(root); + } + + auto resume_tree(bus & root) -> void + { + resume_subtree(root); + } + +} // namespace kapi::devices
\ No newline at end of file |
