Skip to content

Commit d881812

Browse files
nvme::namespace_list: handle unused entries
According to NVM Express® Base Specification, Revision 2.0c 4.4.2 (Namespace List), unused entries in the namespace list are zero filled. Signed-off-by: Andy-Python-Programmer <[email protected]>
1 parent af1603b commit d881812

File tree

4 files changed

+67
-43
lines changed

4 files changed

+67
-43
lines changed

src/aero_kernel/src/drivers/block/nvme/command.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ pub struct IdentifyController {
187187
pub sqes: u8,
188188
pub cqes: u8,
189189
pub maxcmd: u16,
190+
/// This field indicates the maximum value of a valid NSID for the NVM subsystem.
190191
pub nn: u32,
191192
pub oncs: u16,
192193
pub fuses: u16,

src/aero_kernel/src/drivers/block/nvme/dma.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,12 @@ impl<T: ?Sized> core::ops::DerefMut for Dma<T> {
112112
}
113113
}
114114

115+
impl<T: ?Sized + core::fmt::Debug> core::fmt::Debug for Dma<T> {
116+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
117+
f.debug_tuple("Dma").field(&self.0).finish()
118+
}
119+
}
120+
115121
impl<T: ?Sized> Dma<T> {
116122
pub fn addr(&self) -> PhysAddr {
117123
unsafe {

src/aero_kernel/src/drivers/block/nvme/mod.rs

Lines changed: 42 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -363,9 +363,8 @@ impl<'a> Controller<'a> {
363363
io_cq_cmd.prp1 = io_queue.completion_addr().as_u64();
364364
io_cq_cmd.cqid = io_queue.id();
365365
io_cq_cmd.q_size = (io_queue.len() - 1) as u16;
366-
io_cq_cmd.irq_vector = vector as u16;
367-
io_cq_cmd.cq_flags =
368-
(CommandFlags::CQ_IRQ_ENABLED | CommandFlags::QUEUE_PHYS_CONTIG).bits();
366+
io_cq_cmd.irq_vector = 0;
367+
io_cq_cmd.cq_flags = CommandFlags::QUEUE_PHYS_CONTIG.bits();
369368

370369
admin.submit_command(io_cq_cmd);
371370

@@ -376,8 +375,7 @@ impl<'a> Controller<'a> {
376375
io_sq_cmd.cqid = io_queue.id();
377376
io_sq_cmd.sqid = io_queue.id();
378377
io_sq_cmd.q_size = (io_queue.len() - 1) as u16;
379-
io_sq_cmd.sq_flags =
380-
(CommandFlags::CQ_IRQ_ENABLED | CommandFlags::QUEUE_PHYS_CONTIG).bits();
378+
io_sq_cmd.sq_flags = CommandFlags::QUEUE_PHYS_CONTIG.bits();
381379

382380
admin.submit_command(io_sq_cmd);
383381

@@ -396,7 +394,8 @@ impl<'a> Controller<'a> {
396394
io_queue: Mutex::new(io_queue),
397395
});
398396

399-
let namespace_ids = || {
397+
// Discover and initialize the namespaces.
398+
let nsids = {
400399
let nsid_list = Dma::<u32>::new_uninit_slice(this.identity.nn as usize);
401400
let mut nsid_command = IdentifyCommand::default();
402401

@@ -410,48 +409,50 @@ impl<'a> Controller<'a> {
410409
unsafe { nsid_list.assume_init() }
411410
};
412411

413-
// Discover and initialize the namespaces.
414-
let nsids = namespace_ids();
415-
let namespaces = nsids
416-
.iter()
417-
.map(|nsid| {
418-
let identity = Dma::<IdentifyNamespace>::new();
419-
let mut identify_command = IdentifyCommand::default();
420-
421-
identify_command.opcode = AdminOpcode::Identify as u8;
422-
identify_command.cns = IdentifyCns::Namespace as u8;
423-
identify_command.nsid = *nsid;
424-
identify_command.data_ptr.prp1 = identity.addr().as_u64();
425-
426-
this.admin.lock().submit_command(identify_command);
427-
428-
let blocks = identity.nsze as usize;
429-
let block_size = 1 << identity.lbaf[(identity.flbas & 0b11111) as usize].ds;
430-
431-
// The maximum transfer size is in units of 2^(min page size)
432-
let lba_shift = identity.lbaf[(identity.flbas & 0xf) as usize].ds;
433-
let max_lbas = 1 << (max_transfer_shift - lba_shift as usize);
434-
let max_prps = (max_lbas * (1 << lba_shift)) / Size4KiB::SIZE as usize;
435-
436-
Namespace {
437-
controller: this.clone(),
438-
nsid: *nsid,
439-
blocks,
440-
block_size,
441-
size: blocks * block_size,
442-
max_prps,
443-
prps: Mutex::new(Dma::new_uninit_slice(max_prps)),
444-
}
445-
})
446-
.collect::<Vec<_>>();
412+
let mut namespaces = alloc::vec![];
413+
414+
for &nsid in nsids.iter() {
415+
// Unused entries are zero-filled.
416+
if nsid == 0 {
417+
continue;
418+
}
419+
420+
let identity = Dma::<IdentifyNamespace>::new();
421+
let mut identify_command = IdentifyCommand::default();
422+
423+
identify_command.opcode = AdminOpcode::Identify as u8;
424+
identify_command.cns = IdentifyCns::Namespace as u8;
425+
identify_command.nsid = nsid;
426+
identify_command.data_ptr.prp1 = identity.addr().as_u64();
427+
428+
this.admin.lock().submit_command(identify_command);
429+
430+
let blocks = identity.nsze as usize;
431+
let block_size = 1 << identity.lbaf[(identity.flbas & 0b11111) as usize].ds;
432+
433+
// The maximum transfer size is in units of 2^(min page size)
434+
let lba_shift = identity.lbaf[(identity.flbas & 0xf) as usize].ds;
435+
let max_lbas = 1 << (max_transfer_shift - lba_shift as usize);
436+
let max_prps = (max_lbas * (1 << lba_shift)) / Size4KiB::SIZE as usize;
437+
438+
let namespace = Namespace {
439+
controller: this.clone(),
440+
nsid,
441+
blocks,
442+
block_size,
443+
size: blocks * block_size,
444+
max_prps,
445+
prps: Mutex::new(Dma::new_uninit_slice(max_prps)),
446+
};
447447

448-
for namespace in namespaces.iter() {
449448
log::trace!(
450449
"nvme: identified namespace (blocks={}, block_size={}, size={})",
451450
namespace.blocks,
452451
namespace.block_size,
453452
namespace.size
454453
);
454+
455+
namespaces.push(namespace);
455456
}
456457

457458
*this.namespaces.lock() = namespaces;

src/aero_kernel/src/drivers/block/nvme/queue.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,41 @@ pub(super) struct QueuePair<'a> {
109109
id: u16,
110110
size: usize,
111111

112+
cid: u16,
113+
112114
submission: Queue<'a, Submisson>,
113115
completion: Queue<'a, Completion>,
114116
}
115117

116118
impl<'a> QueuePair<'a> {
117119
pub fn new(registers: &Registers, size: usize) -> Result<Self, Error> {
118-
let queue_id = QUEUE_PAIR_ID.fetch_add(2, Ordering::SeqCst);
120+
let queue_id = QUEUE_PAIR_ID.fetch_add(1, Ordering::SeqCst);
119121

120122
Ok(Self {
121123
size,
122124
id: queue_id,
123125

126+
cid: 0,
127+
124128
submission: Queue::new(registers, size, queue_id)?,
125129
completion: Queue::new(registers, size, queue_id)?,
126130
})
127131
}
128132

129133
pub fn submit_command<T: Into<Command>>(&mut self, command: T) {
130-
self.submission.submit_command(command.into());
134+
let mut command = command.into();
135+
136+
unsafe {
137+
// SAFETY: Command Layout:
138+
// - opcode: u8
139+
// - flags: u8
140+
// - command_id: u16 (offset=2 bytes))
141+
*(&mut command as *mut Command as *mut u16).offset(1) = self.cid;
142+
}
143+
144+
self.cid += 1;
145+
146+
self.submission.submit_command(command);
131147
self.completion.next_cmd_result().unwrap();
132148
}
133149

0 commit comments

Comments
 (0)