From 01e1e4e5b91084b3bf303f9c4ce45a7f44c85964 Mon Sep 17 00:00:00 2001 From: Stefan Kalkowski Date: Thu, 27 Oct 2022 14:37:42 +0200 Subject: [PATCH] platform_drv: add "leave_operational" attribute If a device should not be reset, powered off, and its clocks shall stay untouched when it gets released, the leave_operational attribute can be set to true in the device node of the related device inside the devices ROM delivered to the platform driver. This is useful for drivers, which only enable and initialize their device, and can be closed afterwards. Ref genodelabs/genode#4654 --- repos/os/src/drivers/platform/device.cc | 41 +++++++++++-------- repos/os/src/drivers/platform/device.h | 4 +- .../drivers/platform/device_model_policy.cc | 3 +- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/repos/os/src/drivers/platform/device.cc b/repos/os/src/drivers/platform/device.cc index 082d0d8a4b..a4a83e0181 100644 --- a/repos/os/src/drivers/platform/device.cc +++ b/repos/os/src/drivers/platform/device.cc @@ -92,25 +92,27 @@ void Driver::Device::release(Session_component & sc) if (!(_owner == sc)) return; - pci_disable(_env, *this); + if (!_leave_operational) { + pci_disable(_env, *this); - _reset_domain_list.for_each([&] (Reset_domain & r) - { - _model.resets().apply(r.name, [&] (Driver::Reset &reset) { - reset.assert(); }); - }); + _reset_domain_list.for_each([&] (Reset_domain & r) + { + _model.resets().apply(r.name, [&] (Driver::Reset &reset) { + reset.assert(); }); + }); - _power_domain_list.for_each([&] (Power_domain & p) - { - _model.powers().apply(p.name, [&] (Driver::Power &power) { - power.off(); }); - }); + _power_domain_list.for_each([&] (Power_domain & p) + { + _model.powers().apply(p.name, [&] (Driver::Power &power) { + power.off(); }); + }); - _clock_list.for_each([&] (Clock & c) - { - _model.clocks().apply(c.name, [&] (Driver::Clock &clock) { - clock.disable(); }); - }); + _clock_list.for_each([&] (Clock & c) + { + _model.clocks().apply(c.name, [&] (Driver::Clock &clock) { + clock.disable(); }); + }); + } _owner = Owner(); sc.update_devices_rom(); @@ -181,8 +183,11 @@ void Driver::Device::generate(Xml_generator & xml, bool info) const } -Driver::Device::Device(Env & env, Device_model & model, Name name, Type type) -: _env(env), _model(model), _name(name), _type(type) { } +Driver::Device::Device(Env & env, Device_model & model, Name name, Type type, + bool leave_operational) +: + _env(env), _model(model), _name(name), _type(type), + _leave_operational(leave_operational) { } Driver::Device::~Device() diff --git a/repos/os/src/drivers/platform/device.h b/repos/os/src/drivers/platform/device.h index 267c1d50f6..029162e1ab 100644 --- a/repos/os/src/drivers/platform/device.h +++ b/repos/os/src/drivers/platform/device.h @@ -210,7 +210,8 @@ class Driver::Device : private List_model::Element Reserved_memory(Range range) : range(range) {} }; - Device(Env & env, Device_model & model, Name name, Type type); + Device(Env & env, Device_model & model, Name name, Type type, + bool leave_operational); virtual ~Device(); Name name() const; @@ -279,6 +280,7 @@ class Driver::Device : private List_model::Element Device_model & _model; Name const _name; Type const _type; + bool const _leave_operational; Owner _owner {}; List_model _io_mem_list {}; List_model _irq_list {}; diff --git a/repos/os/src/drivers/platform/device_model_policy.cc b/repos/os/src/drivers/platform/device_model_policy.cc index 45a04d8321..cb8745395a 100644 --- a/repos/os/src/drivers/platform/device_model_policy.cc +++ b/repos/os/src/drivers/platform/device_model_policy.cc @@ -71,7 +71,8 @@ Device & Device_model::create_element(Genode::Xml_node node) { Device::Name name = node.attribute_value("name", Device::Name()); Device::Type type = node.attribute_value("type", Device::Type()); - return *(new (_heap) Device(_env, *this, name, type)); + bool leave_operational = node.attribute_value("leave_operational", false); + return *(new (_heap) Device(_env, *this, name, type, leave_operational)); }