1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 23:37:43 +00:00

Kernel: Add polling support to NVMe

Add polling support to NVMe so that it does not use interrupt to
complete a IO but instead actively polls for completion. This probably
is not very efficient in terms of CPU usage but it does not use
interrupts to complete a IO which is beneficial at the moment as there
is no MSI(X) support and it can reduce the latency of an IO in a very
fast NVMe device.

The NVMeQueue class has been made the base class for NVMeInterruptQueue
and NVMePollQueue. The factory function `NVMeQueue::try_create` will
return the appropriate queue to the controller based on the polling
boot parameter.

The polling mode can be enabled by adding an extra boot parameter:
`nvme_poll`.
This commit is contained in:
Pankaj Raghav 2022-01-27 16:44:58 +05:30 committed by Andreas Kling
parent aa832ee251
commit d234e6b801
13 changed files with 211 additions and 83 deletions

View file

@ -44,7 +44,7 @@ bool StorageManagement::boot_argument_contains_partition_uuid()
return m_boot_argument.starts_with(partition_uuid_prefix);
}
UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio)
UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio, bool nvme_poll)
{
VERIFY(m_controllers.is_empty());
@ -60,10 +60,10 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio)
static constexpr PCI::HardwareID vmd_device = { 0x8086, 0x9a0b };
if (device_identifier.hardware_id() == vmd_device) {
auto controller = PCI::VolumeManagementDevice::must_create(device_identifier);
PCI::Access::the().add_host_controller_and_enumerate_attached_devices(move(controller), [this](PCI::DeviceIdentifier const& device_identifier) -> void {
PCI::Access::the().add_host_controller_and_enumerate_attached_devices(move(controller), [this, nvme_poll](PCI::DeviceIdentifier const& device_identifier) -> void {
auto subclass_code = static_cast<SubclassID>(device_identifier.subclass_code().value());
if (subclass_code == SubclassID::NVMeController) {
auto controller = NVMeController::try_initialize(device_identifier);
auto controller = NVMeController::try_initialize(device_identifier, nvme_poll);
if (controller.is_error()) {
dmesgln("Unable to initialize NVMe controller: {}", controller.error());
} else {
@ -84,7 +84,7 @@ UNMAP_AFTER_INIT void StorageManagement::enumerate_controllers(bool force_pio)
m_controllers.append(AHCIController::initialize(device_identifier));
}
if (subclass_code == SubclassID::NVMeController) {
auto controller = NVMeController::try_initialize(device_identifier);
auto controller = NVMeController::try_initialize(device_identifier, nvme_poll);
if (controller.is_error()) {
dmesgln("Unable to initialize NVMe controller: {}", controller.error());
} else {
@ -274,11 +274,11 @@ NonnullRefPtr<FileSystem> StorageManagement::root_filesystem() const
return file_system;
}
UNMAP_AFTER_INIT void StorageManagement::initialize(StringView root_device, bool force_pio)
UNMAP_AFTER_INIT void StorageManagement::initialize(StringView root_device, bool force_pio, bool poll)
{
VERIFY(s_device_minor_number == 0);
m_boot_argument = root_device;
enumerate_controllers(force_pio);
enumerate_controllers(force_pio, poll);
enumerate_storage_devices();
enumerate_disk_partitions();
if (!boot_argument_contains_partition_uuid()) {