mirror of
https://github.com/SerenityOS/serenity.git
synced 2026-11-07 17:52:34 -10:00
Kernel/DeviceTree: Store devices in an IntrusiveList
We never query devices by their name, so using a HashMap is unnecessary. Additionally, the next commit will make it possible for drivers to scan for new child devices and probe drivers on them. This means that the HashMap will then potentially resize while the parent driver is still being probed, causing Device references to get invalid. Now that this code doesn't use a HashMap anymore, we need to ensure that every device is only scanned once, so I added a comment mentioning that requirement. Alternatively, we could store a bool somewhere whether the device was already scanned or not. But there's no good place to put that other than in LibDeviceTree's Node class. However, I don't think we should modify LibDeviceTree for this kernel-specific use case.
This commit is contained in:
1 parent
0e4f404103
commit
bfda800128
3 files changed
+18
-9
No files matched your search
@@ -7,6 +7,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <AK/Badge.h>
|
||||
#include <AK/IntrusiveList.h>
|
||||
#include <AK/Noncopyable.h>
|
||||
#include <Kernel/Memory/PhysicalAddress.h>
|
||||
#include <LibDeviceTree/DeviceTree.h>
|
||||
@@ -51,6 +52,11 @@ private:
|
||||
::DeviceTree::Node const* m_node;
|
||||
StringView m_node_name;
|
||||
Driver const* m_driver { nullptr };
|
||||
|
||||
IntrusiveListNode<Device> m_list_node;
|
||||
|
||||
public:
|
||||
using List = IntrusiveList<&Device::m_list_node>;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <[email protected]>
|
||||
* Copyright (c) 2024-2026, Sönke Holz <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@@ -54,6 +54,8 @@ ErrorOr<size_t> Management::resolve_interrupt_number(::DeviceTree::Interrupt int
|
||||
return maybe_interrupt_controller.value()->translate_interrupt_specifier_to_interrupt_number(interrupt.interrupt_specifier);
|
||||
}
|
||||
|
||||
// NOTE: This function has to only be called once for each device!
|
||||
// Otherwise duplicate `DeviceTree::Device`s may be created for each node.
|
||||
ErrorOr<void> Management::scan_node_for_devices(::DeviceTree::Node const& node)
|
||||
{
|
||||
for (auto const& [child_name, child] : node.children()) {
|
||||
@@ -65,8 +67,11 @@ ErrorOr<void> Management::scan_node_for_devices(::DeviceTree::Node const& node)
|
||||
if (maybe_status.has_value() && maybe_status->as_string() != "okay" && !ignore_status_disabled)
|
||||
continue;
|
||||
|
||||
if (TRY(m_devices.try_set(&child, Device { child, child_name })) != HashSetResult::InsertedNewEntry)
|
||||
continue;
|
||||
auto* device = new (nothrow) Device { child, child_name };
|
||||
if (device == nullptr)
|
||||
return ENOMEM;
|
||||
|
||||
m_devices.append(*device);
|
||||
|
||||
if (child.is_compatible_with("simple-bus"sv)) {
|
||||
TRY(scan_node_for_devices(child));
|
||||
@@ -92,13 +97,11 @@ bool Management::attach_device_to_driver(Device& device, Driver const& driver, S
|
||||
|
||||
ErrorOr<void> Management::probe_drivers(Driver::ProbeStage probe_stage)
|
||||
{
|
||||
for (auto& [device_node, device] : m_devices) {
|
||||
VERIFY(device_node != nullptr);
|
||||
|
||||
for (auto& device : m_devices) {
|
||||
if (device.driver() != nullptr)
|
||||
continue;
|
||||
|
||||
auto maybe_compatible = device_node->get_property("compatible"sv);
|
||||
auto maybe_compatible = device.node().get_property("compatible"sv);
|
||||
if (!maybe_compatible.has_value())
|
||||
continue;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Sönke Holz <[email protected]>
|
||||
* Copyright (c) 2024-2026, Sönke Holz <[email protected]>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
@@ -33,7 +33,7 @@ private:
|
||||
Vector<NonnullOwnPtr<Driver>> m_drivers;
|
||||
HashMap<StringView, Driver*> m_driver_by_compatible_string;
|
||||
|
||||
HashMap<::DeviceTree::Node const*, Device> m_devices;
|
||||
Device::List m_devices;
|
||||
|
||||
HashMap<::DeviceTree::Node const*, DeviceTree::InterruptController const*> m_interrupt_controllers;
|
||||
};
|
||||
|
||||
Reference in new issue
Block a user