Skip to content

Commit 30bb138

Browse files
authored
NVMe: Enable IO queue deletion plus some init/reset cleanup. (#58)
1 parent c3558de commit 30bb138

File tree

5 files changed

+365
-61
lines changed

5 files changed

+365
-61
lines changed

propolis/src/hw/nvme/admin.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::cmp::min;
22
use std::mem::size_of;
33

44
use super::bits::{self, *};
5+
use super::queue::{QueueId, ADMIN_QUEUE_ID};
56
use crate::common::GuestAddr;
67
use crate::{common::PAGE_SIZE, dispatch::DispCtx};
78

@@ -16,6 +17,14 @@ impl NvmeCtrl {
1617
cmd: &cmds::CreateIOCQCmd,
1718
ctx: &DispCtx,
1819
) -> cmds::Completion {
20+
// If the host hasn't specified an IOCQES, fail this request
21+
if self.ctrl.cc.iocqes() == 0 {
22+
return cmds::Completion::specific_err(
23+
StatusCodeType::CmdSpecific,
24+
STS_CREATE_IO_Q_INVAL_QSIZE,
25+
);
26+
}
27+
1928
if cmd.intr_vector >= super::NVME_MSIX_COUNT {
2029
return cmds::Completion::specific_err(
2130
StatusCodeType::CmdSpecific,
@@ -57,6 +66,14 @@ impl NvmeCtrl {
5766
cmd: &cmds::CreateIOSQCmd,
5867
ctx: &DispCtx,
5968
) -> cmds::Completion {
69+
// If the host hasn't specified an IOSQES, fail this request
70+
if self.ctrl.cc.iosqes() == 0 {
71+
return cmds::Completion::specific_err(
72+
StatusCodeType::CmdSpecific,
73+
STS_CREATE_IO_Q_INVAL_QSIZE,
74+
);
75+
}
76+
6077
// We only support physical contiguous queues
6178
if !cmd.phys_contig {
6279
return cmds::Completion::generic_err(bits::STS_INVAL_FIELD);
@@ -89,6 +106,79 @@ impl NvmeCtrl {
89106
}
90107
}
91108

109+
/// Service I/O Delete Completion Queue command.
110+
///
111+
/// See NVMe 1.0e Section 5.5 Delete I/O Submission Queue command
112+
pub(super) fn acmd_delete_io_cq(
113+
&mut self,
114+
cqid: QueueId,
115+
_ctx: &DispCtx,
116+
) -> cmds::Completion {
117+
// Not allowed to delete the Admin Completion Queue
118+
if cqid == ADMIN_QUEUE_ID {
119+
return cmds::Completion::specific_err(
120+
StatusCodeType::CmdSpecific,
121+
STS_DELETE_IO_Q_INVAL_QID,
122+
);
123+
}
124+
125+
// Remove the CQ from our list of active CQs.
126+
// At this point, all associated SQs should've been deleted
127+
// otherwise we'll return an error.
128+
match self.delete_cq(cqid) {
129+
Ok(()) => cmds::Completion::success(),
130+
Err(NvmeError::InvalidCompQueue(_)) => {
131+
cmds::Completion::specific_err(
132+
StatusCodeType::CmdSpecific,
133+
STS_DELETE_IO_Q_INVAL_QID,
134+
)
135+
}
136+
Err(NvmeError::AssociatedSubQueuesStillExist(_, _)) => {
137+
cmds::Completion::specific_err(
138+
StatusCodeType::CmdSpecific,
139+
STS_DELETE_IO_Q_INVAL_Q_DELETION,
140+
)
141+
}
142+
_ => cmds::Completion::generic_err(STS_INTERNAL_ERR),
143+
}
144+
}
145+
146+
/// Service I/O Delete Submission Queue command.
147+
///
148+
/// See NVMe 1.0e Section 5.6 Delete I/O Submission Queue command
149+
pub(super) fn acmd_delete_io_sq(
150+
&mut self,
151+
sqid: QueueId,
152+
_ctx: &DispCtx,
153+
) -> cmds::Completion {
154+
// Not allowed to delete the Admin Submission Queue
155+
if sqid == ADMIN_QUEUE_ID {
156+
return cmds::Completion::specific_err(
157+
StatusCodeType::CmdSpecific,
158+
STS_DELETE_IO_Q_INVAL_QID,
159+
);
160+
}
161+
162+
// Remove the SQ from our list of active SQs which will stop
163+
// us from accepting any new requests for it.
164+
// That should be the only strong ref left to the SubQueue
165+
// Any in-flight I/O requests that haven't been completed yet
166+
// only hold a weak ref (via CompQueueEntryPermit).
167+
// Note: The NVMe 1.0e spec says "The command causes all commands
168+
// submitted to the indicated Submission Queue that are still in
169+
// progress to be aborted."
170+
match self.delete_sq(sqid) {
171+
Ok(()) => cmds::Completion::success(),
172+
Err(NvmeError::InvalidSubQueue(_)) => {
173+
cmds::Completion::specific_err(
174+
StatusCodeType::CmdSpecific,
175+
STS_DELETE_IO_Q_INVAL_QID,
176+
)
177+
}
178+
_ => cmds::Completion::generic_err(STS_INTERNAL_ERR),
179+
}
180+
}
181+
92182
/// Service Get Log Page command.
93183
///
94184
/// See NVMe 1.0e Section 5.10 Get Log Page command

propolis/src/hw/nvme/bits.rs

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ bitstruct! {
235235
/// Representation of the Controller Configuration (CC) register.
236236
///
237237
/// See NVMe 1.0e Section 3.1.5 Offset 14h: CC - Controller Configuration
238-
#[derive(Clone, Copy, Debug, Default)]
238+
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
239239
pub struct Configuration(pub u32) {
240240
/// Enable (EN)
241241
///
@@ -291,7 +291,7 @@ bitstruct! {
291291
}
292292

293293
// Selected IO Command Set
294-
#[derive(Clone, Copy, Debug)]
294+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
295295
pub enum IOCommandSet {
296296
Nvm,
297297
Reserved(u8),
@@ -317,7 +317,7 @@ impl bitstruct::IntoRaw<u8, IOCommandSet> for Configuration {
317317
}
318318

319319
/// Arbitration Mechanisms
320-
#[derive(Clone, Copy, Debug)]
320+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
321321
pub enum ArbitrationMechanism {
322322
RoundRobin,
323323
WeightedRoundRobinWithUrgent,
@@ -583,15 +583,21 @@ pub const STS_COMMAND_SEQ_ERR: u8 = 0xC;
583583
/// Completion Queue Invalid
584584
pub const STS_CREATE_IO_Q_INVAL_CQ: u8 = 0x0;
585585

586-
/// Invalid Queue Identifier
586+
/// Invalid Queue Identifier (Queue Creation)
587587
pub const STS_CREATE_IO_Q_INVAL_QID: u8 = 0x1;
588588

589-
/// Invalid Queue Size
589+
/// Invalid Queue Size (Queue Creation)
590590
pub const STS_CREATE_IO_Q_INVAL_QSIZE: u8 = 0x2;
591591

592-
/// Invalid Interrupt Vector
592+
/// Invalid Interrupt Vector (Queue Creation)
593593
pub const STS_CREATE_IO_Q_INVAL_INT_VEC: u8 = 0x8;
594594

595+
/// Invalid Queue Identifier (Queue Deletion)
596+
pub const STS_DELETE_IO_Q_INVAL_QID: u8 = 0x1;
597+
598+
/// Invalid Queue Deletion
599+
pub const STS_DELETE_IO_Q_INVAL_Q_DELETION: u8 = 0xC;
600+
595601
// NVM Command Specific Status values
596602
// See NVMe 1.0e Section 4.5.1.2.2, Figure 20 Status Code - Command Specific Status Values, NVM Command Set
597603

propolis/src/hw/nvme/cmds.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,12 @@ impl From<QueueCreateErr> for Completion {
784784
StatusCodeType::CmdSpecific,
785785
bits::STS_CREATE_IO_Q_INVAL_QSIZE,
786786
),
787+
QueueCreateErr::SubQueueIdAlreadyExists(_) => {
788+
Completion::specific_err(
789+
StatusCodeType::CmdSpecific,
790+
bits::STS_CREATE_IO_Q_INVAL_QID,
791+
)
792+
}
787793
}
788794
}
789795
}

0 commit comments

Comments
 (0)