Serenity Operating System
at master 62 lines 2.4 kB view raw
1/* 2 * Copyright (c) 2022, Pankaj R <pankydev8@gmail.com> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <Kernel/Devices/BlockDevice.h> 8#include <Kernel/Storage/NVMe/NVMeDefinitions.h> 9#include <Kernel/Storage/NVMe/NVMeInterruptQueue.h> 10#include <Kernel/WorkQueue.h> 11 12namespace Kernel { 13 14UNMAP_AFTER_INIT NVMeInterruptQueue::NVMeInterruptQueue(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, Vector<NonnullRefPtr<Memory::PhysicalPage>> cq_dma_page, OwnPtr<Memory::Region> sq_dma_region, Vector<NonnullRefPtr<Memory::PhysicalPage>> sq_dma_page, Memory::TypedMapping<DoorbellRegister volatile> db_regs) 15 : NVMeQueue(move(rw_dma_region), rw_dma_page, qid, q_depth, move(cq_dma_region), cq_dma_page, move(sq_dma_region), sq_dma_page, move(db_regs)) 16 , IRQHandler(irq) 17{ 18 enable_irq(); 19} 20 21bool NVMeInterruptQueue::handle_irq(RegisterState const&) 22{ 23 SpinlockLocker lock(m_request_lock); 24 return process_cq() ? true : false; 25} 26 27void NVMeInterruptQueue::submit_sqe(NVMeSubmission& sub) 28{ 29 NVMeQueue::submit_sqe(sub); 30} 31 32void NVMeInterruptQueue::complete_current_request(u16 status) 33{ 34 VERIFY(m_request_lock.is_locked()); 35 36 auto work_item_creation_result = g_io_work->try_queue([this, status]() { 37 SpinlockLocker lock(m_request_lock); 38 auto current_request = m_current_request; 39 m_current_request.clear(); 40 if (status) { 41 lock.unlock(); 42 current_request->complete(AsyncBlockDeviceRequest::Failure); 43 return; 44 } 45 if (current_request->request_type() == AsyncBlockDeviceRequest::RequestType::Read) { 46 if (auto result = current_request->write_to_buffer(current_request->buffer(), m_rw_dma_region->vaddr().as_ptr(), current_request->buffer_size()); result.is_error()) { 47 lock.unlock(); 48 current_request->complete(AsyncDeviceRequest::MemoryFault); 49 return; 50 } 51 } 52 lock.unlock(); 53 current_request->complete(AsyncDeviceRequest::Success); 54 return; 55 }); 56 if (work_item_creation_result.is_error()) { 57 auto current_request = m_current_request; 58 m_current_request.clear(); 59 current_request->complete(AsyncDeviceRequest::OutOfMemory); 60 } 61} 62}