1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 01:57:45 +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

@ -27,45 +27,47 @@ struct DoorbellRegister {
};
class AsyncBlockDeviceRequest;
class NVMeQueue : public IRQHandler
, public RefCounted<NVMeQueue> {
class NVMeQueue : public RefCounted<NVMeQueue> {
public:
static ErrorOr<NonnullRefPtr<NVMeQueue>> try_create(u16 qid, u8 irq, u32 q_depth, OwnPtr<Memory::Region> cq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> cq_dma_page, OwnPtr<Memory::Region> sq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> sq_dma_page, Memory::TypedMapping<volatile DoorbellRegister> db_regs);
static ErrorOr<NonnullRefPtr<NVMeQueue>> try_create(u16 qid, Optional<u8> irq, u32 q_depth, OwnPtr<Memory::Region> cq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> cq_dma_page, OwnPtr<Memory::Region> sq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> sq_dma_page, Memory::TypedMapping<volatile DoorbellRegister> db_regs);
bool is_admin_queue() { return m_admin_queue; };
void submit_sqe(NVMeSubmission&);
u16 submit_sync_sqe(NVMeSubmission&);
void read(AsyncBlockDeviceRequest& request, u16 nsid, u64 index, u32 count);
void write(AsyncBlockDeviceRequest& request, u16 nsid, u64 index, u32 count);
void enable_interrupts() { enable_irq(); };
void disable_interrupts() { disable_irq(); };
virtual void submit_sqe(NVMeSubmission&);
virtual ~NVMeQueue();
protected:
u32 process_cq();
void update_sq_doorbell()
{
m_db_regs->sq_tail = m_sq_tail;
}
NVMeQueue(NonnullOwnPtr<Memory::Region> rw_dma_region, Memory::PhysicalPage const& rw_dma_page, u16 qid, u32 q_depth, OwnPtr<Memory::Region> cq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> cq_dma_page, OwnPtr<Memory::Region> sq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> sq_dma_page, Memory::TypedMapping<volatile DoorbellRegister> db_regs);
private:
NVMeQueue(NonnullOwnPtr<Memory::Region> rw_dma_region, Memory::PhysicalPage const& rw_dma_page, u16 qid, u8 irq, u32 q_depth, OwnPtr<Memory::Region> cq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> cq_dma_page, OwnPtr<Memory::Region> sq_dma_region, NonnullRefPtrVector<Memory::PhysicalPage> sq_dma_page, Memory::TypedMapping<volatile DoorbellRegister> db_regs);
virtual bool handle_irq(const RegisterState&) override;
bool cqe_available();
void update_cqe_head();
void complete_current_request(u16 status);
virtual void complete_current_request(u16 status) = 0;
void update_cq_doorbell()
{
m_db_regs->cq_head = m_cq_head;
}
void update_sq_doorbell()
{
m_db_regs->sq_tail = m_sq_tail;
}
protected:
Spinlock m_cq_lock { LockRank::Interrupts };
RefPtr<AsyncBlockDeviceRequest> m_current_request;
NonnullOwnPtr<Memory::Region> m_rw_dma_region;
Spinlock m_request_lock;
private:
u16 m_qid {};
u8 m_cq_valid_phase { 1 };
u16 m_sq_tail {};
u16 m_prev_sq_tail {};
u16 m_cq_head {};
bool m_admin_queue { false };
u8 m_irq {};
u32 m_qdepth {};
Spinlock m_cq_lock { LockRank::Interrupts };
Spinlock m_sq_lock { LockRank::Interrupts };
OwnPtr<Memory::Region> m_cq_dma_region;
NonnullRefPtrVector<Memory::PhysicalPage> m_cq_dma_page;
@ -73,10 +75,7 @@ private:
OwnPtr<Memory::Region> m_sq_dma_region;
NonnullRefPtrVector<Memory::PhysicalPage> m_sq_dma_page;
Span<NVMeCompletion> m_cqe_array;
NonnullOwnPtr<Memory::Region> m_rw_dma_region;
Memory::TypedMapping<volatile DoorbellRegister> m_db_regs;
NonnullRefPtr<Memory::PhysicalPage> m_rw_dma_page;
Spinlock m_request_lock;
RefPtr<AsyncBlockDeviceRequest> m_current_request;
};
}