diff --git a/Kernel/Devices/Storage/NVMe/NVMeController.cpp b/Kernel/Devices/Storage/NVMe/NVMeController.cpp index 32c0c6f08d..f2898372a2 100644 --- a/Kernel/Devices/Storage/NVMe/NVMeController.cpp +++ b/Kernel/Devices/Storage/NVMe/NVMeController.cpp @@ -54,8 +54,10 @@ UNMAP_AFTER_INIT ErrorOr NVMeController::initialize(bool is_queue_polled) m_ready_timeout = Duration::from_milliseconds((CAP_TO(caps) + 1) * 500); // CAP.TO is in 500ms units calculate_doorbell_stride(); - // IO queues + 1 admin queue - m_irq_type = TRY(reserve_irqs(nr_of_queues + 1, true)); + if (queue_type == QueueType::IRQ) { + // IO queues + 1 admin queue + m_irq_type = TRY(reserve_irqs(nr_of_queues + 1, true)); + } TRY(create_admin_queue(queue_type)); VERIFY(m_admin_queue_ready == true); @@ -351,7 +353,9 @@ UNMAP_AFTER_INIT ErrorOr NVMeController::create_admin_queue(QueueType queu m_controller_regs->acq = reinterpret_cast(AK::convert_between_host_and_little_endian(cq_dma_pages.first()->paddr().as_ptr())); m_controller_regs->asq = reinterpret_cast(AK::convert_between_host_and_little_endian(sq_dma_pages.first()->paddr().as_ptr())); - auto irq = TRY(allocate_irq(0)); // Admin queue always uses the 0th index when using MSIx + Optional irq; + if (queue_type == QueueType::IRQ) + irq = TRY(allocate_irq(0)); // Admin queue always uses the 0th index when using MSIx maybe_error = start_controller(); if (maybe_error.is_error()) { @@ -398,7 +402,10 @@ UNMAP_AFTER_INIT ErrorOr NVMeController::create_io_queue(u8 qid, QueueType auto flags = (queue_type == QueueType::IRQ) ? QUEUE_IRQ_ENABLED : QUEUE_IRQ_DISABLED; flags |= QUEUE_PHY_CONTIGUOUS; // When using MSIx interrupts, qid is used as an index into the interrupt table - sub.create_cq.irq_vector = (m_irq_type == PCI::InterruptType::PIN) ? 0 : qid; + if (m_irq_type.has_value() && m_irq_type.value() != PCI::InterruptType::PIN) + sub.create_cq.irq_vector = qid; + else + sub.create_cq.irq_vector = 0; sub.create_cq.cq_flags = AK::convert_between_host_and_little_endian(flags & 0xFFFF); submit_admin_command(sub, true); } diff --git a/Kernel/Devices/Storage/NVMe/NVMeController.h b/Kernel/Devices/Storage/NVMe/NVMeController.h index f3c2f96c25..7597285d5c 100644 --- a/Kernel/Devices/Storage/NVMe/NVMeController.h +++ b/Kernel/Devices/Storage/NVMe/NVMeController.h @@ -80,7 +80,7 @@ private: AK::Duration m_ready_timeout; PhysicalAddress m_bar { 0 }; u8 m_dbl_stride { 0 }; - PCI::InterruptType m_irq_type; + Optional m_irq_type; QueueType m_queue_type { QueueType::IRQ }; static Atomic s_controller_id; }; diff --git a/Kernel/Devices/Storage/NVMe/NVMeQueue.cpp b/Kernel/Devices/Storage/NVMe/NVMeQueue.cpp index 8e2787e909..48847f0e6b 100644 --- a/Kernel/Devices/Storage/NVMe/NVMeQueue.cpp +++ b/Kernel/Devices/Storage/NVMe/NVMeQueue.cpp @@ -12,7 +12,7 @@ #include namespace Kernel { -ErrorOr> NVMeQueue::try_create(NVMeController& device, u16 qid, u8 irq, u32 q_depth, OwnPtr cq_dma_region, OwnPtr sq_dma_region, Doorbell db_regs, QueueType queue_type) +ErrorOr> NVMeQueue::try_create(NVMeController& device, u16 qid, Optional irq, u32 q_depth, OwnPtr cq_dma_region, OwnPtr sq_dma_region, Doorbell db_regs, QueueType queue_type) { // Note: Allocate DMA region for RW operation. For now the requests don't exceed more than 4096 bytes (Storage device takes care of it) RefPtr rw_dma_page; @@ -26,7 +26,7 @@ ErrorOr> NVMeQueue::try_create(NVMeController& devi return queue; } - auto queue = NVMeInterruptQueue::try_create(device, move(rw_dma_region), rw_dma_page.release_nonnull(), qid, irq, q_depth, move(cq_dma_region), move(sq_dma_region), move(db_regs)); + auto queue = NVMeInterruptQueue::try_create(device, move(rw_dma_region), rw_dma_page.release_nonnull(), qid, irq.release_value(), q_depth, move(cq_dma_region), move(sq_dma_region), move(db_regs)); return queue; } diff --git a/Kernel/Devices/Storage/NVMe/NVMeQueue.h b/Kernel/Devices/Storage/NVMe/NVMeQueue.h index b088e0180a..d93543c865 100644 --- a/Kernel/Devices/Storage/NVMe/NVMeQueue.h +++ b/Kernel/Devices/Storage/NVMe/NVMeQueue.h @@ -52,7 +52,7 @@ struct NVMeIO { class NVMeController; class NVMeQueue : public AtomicRefCounted { public: - static ErrorOr> try_create(NVMeController& device, u16 qid, u8 irq, u32 q_depth, OwnPtr cq_dma_region, OwnPtr sq_dma_region, Doorbell db_regs, QueueType queue_type); + static ErrorOr> try_create(NVMeController& device, u16 qid, Optional irq, u32 q_depth, OwnPtr cq_dma_region, OwnPtr sq_dma_region, Doorbell db_regs, QueueType queue_type); bool is_admin_queue() { return m_admin_queue; } u16 submit_sync_sqe(NVMeSubmission&); void read(AsyncBlockDeviceRequest& request, u16 nsid, u64 index, u32 count);