mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 15:40:19 +00:00
Kernel/Net: Allocate regions before invoking Intel driver constructors
Instead of allocating after the construction point ensure that all Intel drivers are allocating necessary buffer regions and then pass them to the constructors. This could let us fail early in case of OOM, so we don't touch a network adapter before we ensure we have all the appropriate mappings in place.
This commit is contained in:
parent
301f9de915
commit
102186b0f5
Notes:
sideshowbarker
2024-07-17 04:10:16 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/102186b0f5 Pull-request: https://github.com/SerenityOS/serenity/pull/16557 Reviewed-by: https://github.com/ADKaster
4 changed files with 62 additions and 19 deletions
|
@ -190,7 +190,20 @@ UNMAP_AFTER_INIT ErrorOr<LockRefPtr<E1000ENetworkAdapter>> E1000ENetworkAdapter:
|
|||
u8 irq = pci_device_identifier.interrupt_line().value();
|
||||
auto interface_name = TRY(NetworkingManagement::generate_interface_name_from_pci_address(pci_device_identifier));
|
||||
auto registers_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_device_identifier, PCI::HeaderType0BaseRegister::BAR0));
|
||||
auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) E1000ENetworkAdapter(pci_device_identifier.address(), irq, move(registers_io_window), move(interface_name))));
|
||||
|
||||
auto rx_buffer_region = TRY(MM.allocate_contiguous_kernel_region(rx_buffer_size * number_of_rx_descriptors, "E1000 RX buffers"sv, Memory::Region::Access::ReadWrite));
|
||||
auto tx_buffer_region = MM.allocate_contiguous_kernel_region(tx_buffer_size * number_of_tx_descriptors, "E1000 TX buffers"sv, Memory::Region::Access::ReadWrite).release_value();
|
||||
auto rx_descriptors_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(sizeof(e1000_rx_desc) * number_of_rx_descriptors)), "E1000 RX Descriptors"sv, Memory::Region::Access::ReadWrite));
|
||||
auto tx_descriptors_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(sizeof(e1000_tx_desc) * number_of_tx_descriptors)), "E1000 TX Descriptors"sv, Memory::Region::Access::ReadWrite));
|
||||
|
||||
auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) E1000ENetworkAdapter(pci_device_identifier.address(),
|
||||
irq, move(registers_io_window),
|
||||
move(rx_buffer_region),
|
||||
move(tx_buffer_region),
|
||||
move(rx_descriptors_region),
|
||||
move(tx_descriptors_region),
|
||||
move(interface_name))));
|
||||
|
||||
if (!adapter->initialize())
|
||||
return Error::from_string_literal("E1000ENetworkAdapter: Unable to initialize adapter");
|
||||
return adapter;
|
||||
|
@ -217,8 +230,16 @@ UNMAP_AFTER_INIT bool E1000ENetworkAdapter::initialize()
|
|||
return true;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT E1000ENetworkAdapter::E1000ENetworkAdapter(PCI::Address address, u8 irq, NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<KString> interface_name)
|
||||
: E1000NetworkAdapter(address, irq, move(registers_io_window), move(interface_name))
|
||||
UNMAP_AFTER_INIT E1000ENetworkAdapter::E1000ENetworkAdapter(PCI::Address address, u8 irq,
|
||||
NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<Memory::Region> rx_buffer_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_buffer_region, NonnullOwnPtr<Memory::Region> rx_descriptors_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_descriptors_region, NonnullOwnPtr<KString> interface_name)
|
||||
: E1000NetworkAdapter(address, irq, move(registers_io_window),
|
||||
move(rx_buffer_region),
|
||||
move(tx_buffer_region),
|
||||
move(rx_descriptors_region),
|
||||
move(tx_descriptors_region),
|
||||
move(interface_name))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,10 @@ public:
|
|||
virtual StringView purpose() const override { return class_name(); }
|
||||
|
||||
private:
|
||||
E1000ENetworkAdapter(PCI::Address, u8 irq, NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<KString>);
|
||||
E1000ENetworkAdapter(PCI::Address, u8 irq,
|
||||
NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<Memory::Region> rx_buffer_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_buffer_region, NonnullOwnPtr<Memory::Region> rx_descriptors_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_descriptors_region, NonnullOwnPtr<KString>);
|
||||
|
||||
virtual StringView class_name() const override { return "E1000ENetworkAdapter"sv; }
|
||||
|
||||
|
|
|
@ -168,9 +168,20 @@ UNMAP_AFTER_INIT ErrorOr<LockRefPtr<E1000NetworkAdapter>> E1000NetworkAdapter::t
|
|||
u8 irq = pci_device_identifier.interrupt_line().value();
|
||||
auto interface_name = TRY(NetworkingManagement::generate_interface_name_from_pci_address(pci_device_identifier));
|
||||
auto registers_io_window = TRY(IOWindow::create_for_pci_device_bar(pci_device_identifier, PCI::HeaderType0BaseRegister::BAR0));
|
||||
auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) E1000NetworkAdapter(pci_device_identifier.address(), irq, move(registers_io_window), move(interface_name))));
|
||||
adapter->m_rx_descriptors_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(sizeof(e1000_rx_desc) * number_of_rx_descriptors)), "E1000 RX Descriptors"sv, Memory::Region::Access::ReadWrite));
|
||||
adapter->m_tx_descriptors_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(sizeof(e1000_tx_desc) * number_of_tx_descriptors)), "E1000 TX Descriptors"sv, Memory::Region::Access::ReadWrite));
|
||||
|
||||
auto rx_buffer_region = TRY(MM.allocate_contiguous_kernel_region(rx_buffer_size * number_of_rx_descriptors, "E1000 RX buffers"sv, Memory::Region::Access::ReadWrite));
|
||||
auto tx_buffer_region = MM.allocate_contiguous_kernel_region(tx_buffer_size * number_of_tx_descriptors, "E1000 TX buffers"sv, Memory::Region::Access::ReadWrite).release_value();
|
||||
auto rx_descriptors_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(sizeof(e1000_rx_desc) * number_of_rx_descriptors)), "E1000 RX Descriptors"sv, Memory::Region::Access::ReadWrite));
|
||||
auto tx_descriptors_region = TRY(MM.allocate_contiguous_kernel_region(TRY(Memory::page_round_up(sizeof(e1000_tx_desc) * number_of_tx_descriptors)), "E1000 TX Descriptors"sv, Memory::Region::Access::ReadWrite));
|
||||
|
||||
auto adapter = TRY(adopt_nonnull_lock_ref_or_enomem(new (nothrow) E1000NetworkAdapter(pci_device_identifier.address(),
|
||||
irq, move(registers_io_window),
|
||||
move(rx_buffer_region),
|
||||
move(tx_buffer_region),
|
||||
move(rx_descriptors_region),
|
||||
move(tx_descriptors_region),
|
||||
move(interface_name))));
|
||||
|
||||
if (!adapter->initialize())
|
||||
return Error::from_string_literal("E1000NetworkAdapter: Unable to initialize adapter");
|
||||
return adapter;
|
||||
|
@ -215,11 +226,18 @@ UNMAP_AFTER_INIT bool E1000NetworkAdapter::initialize()
|
|||
return true;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address address, u8 irq, NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<KString> interface_name)
|
||||
UNMAP_AFTER_INIT E1000NetworkAdapter::E1000NetworkAdapter(PCI::Address address, u8 irq,
|
||||
NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<Memory::Region> rx_buffer_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_buffer_region, NonnullOwnPtr<Memory::Region> rx_descriptors_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_descriptors_region, NonnullOwnPtr<KString> interface_name)
|
||||
: NetworkAdapter(move(interface_name))
|
||||
, PCI::Device(address)
|
||||
, IRQHandler(irq)
|
||||
, m_registers_io_window(move(registers_io_window))
|
||||
, m_rx_descriptors_region(move(rx_descriptors_region))
|
||||
, m_tx_descriptors_region(move(tx_descriptors_region))
|
||||
, m_rx_buffer_region(move(rx_buffer_region))
|
||||
, m_tx_buffer_region(move(tx_buffer_region))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -308,10 +326,7 @@ UNMAP_AFTER_INIT void E1000NetworkAdapter::read_mac_address()
|
|||
UNMAP_AFTER_INIT void E1000NetworkAdapter::initialize_rx_descriptors()
|
||||
{
|
||||
auto* rx_descriptors = (e1000_tx_desc*)m_rx_descriptors_region->vaddr().as_ptr();
|
||||
constexpr auto rx_buffer_size = 8192;
|
||||
constexpr auto rx_buffer_page_count = rx_buffer_size / PAGE_SIZE;
|
||||
|
||||
m_rx_buffer_region = MM.allocate_contiguous_kernel_region(rx_buffer_size * number_of_rx_descriptors, "E1000 RX buffers"sv, Memory::Region::Access::ReadWrite).release_value();
|
||||
for (size_t i = 0; i < number_of_rx_descriptors; ++i) {
|
||||
auto& descriptor = rx_descriptors[i];
|
||||
m_rx_buffers[i] = m_rx_buffer_region->vaddr().as_ptr() + rx_buffer_size * i;
|
||||
|
@ -331,10 +346,7 @@ UNMAP_AFTER_INIT void E1000NetworkAdapter::initialize_rx_descriptors()
|
|||
UNMAP_AFTER_INIT void E1000NetworkAdapter::initialize_tx_descriptors()
|
||||
{
|
||||
auto* tx_descriptors = (e1000_tx_desc*)m_tx_descriptors_region->vaddr().as_ptr();
|
||||
|
||||
constexpr auto tx_buffer_size = 8192;
|
||||
constexpr auto tx_buffer_page_count = tx_buffer_size / PAGE_SIZE;
|
||||
m_tx_buffer_region = MM.allocate_contiguous_kernel_region(tx_buffer_size * number_of_tx_descriptors, "E1000 TX buffers"sv, Memory::Region::Access::ReadWrite).release_value();
|
||||
|
||||
for (size_t i = 0; i < number_of_tx_descriptors; ++i) {
|
||||
auto& descriptor = tx_descriptors[i];
|
||||
|
|
|
@ -35,10 +35,17 @@ public:
|
|||
virtual StringView device_name() const override { return "E1000"sv; }
|
||||
|
||||
protected:
|
||||
static constexpr size_t rx_buffer_size = 8192;
|
||||
static constexpr size_t tx_buffer_size = 8192;
|
||||
|
||||
void setup_interrupts();
|
||||
void setup_link();
|
||||
|
||||
E1000NetworkAdapter(PCI::Address, u8 irq, NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<KString>);
|
||||
E1000NetworkAdapter(PCI::Address, u8 irq,
|
||||
NonnullOwnPtr<IOWindow> registers_io_window, NonnullOwnPtr<Memory::Region> rx_buffer_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_buffer_region, NonnullOwnPtr<Memory::Region> rx_descriptors_region,
|
||||
NonnullOwnPtr<Memory::Region> tx_descriptors_region, NonnullOwnPtr<KString>);
|
||||
|
||||
virtual bool handle_irq(RegisterState const&) override;
|
||||
virtual StringView class_name() const override { return "E1000NetworkAdapter"sv; }
|
||||
|
||||
|
@ -85,10 +92,10 @@ protected:
|
|||
|
||||
NonnullOwnPtr<IOWindow> m_registers_io_window;
|
||||
|
||||
OwnPtr<Memory::Region> m_rx_descriptors_region;
|
||||
OwnPtr<Memory::Region> m_tx_descriptors_region;
|
||||
OwnPtr<Memory::Region> m_rx_buffer_region;
|
||||
OwnPtr<Memory::Region> m_tx_buffer_region;
|
||||
NonnullOwnPtr<Memory::Region> m_rx_descriptors_region;
|
||||
NonnullOwnPtr<Memory::Region> m_tx_descriptors_region;
|
||||
NonnullOwnPtr<Memory::Region> m_rx_buffer_region;
|
||||
NonnullOwnPtr<Memory::Region> m_tx_buffer_region;
|
||||
Array<void*, number_of_rx_descriptors> m_rx_buffers;
|
||||
Array<void*, number_of_tx_descriptors> m_tx_buffers;
|
||||
bool m_has_eeprom { false };
|
||||
|
|
Loading…
Reference in a new issue