Skip to content

Commit 5b27779

Browse files
committed
nvme: mi: dev: Implement Admin / Get Log Page / SMART Health Information Log Page
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
1 parent 1d1a544 commit 5b27779

File tree

5 files changed

+967
-19
lines changed

5 files changed

+967
-19
lines changed

src/lib.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use deku::{DekuContainerWrite, DekuError};
88
use flagset::FlagSet;
99
use hmac::Mac;
1010
use mctp::AsyncRespChannel;
11-
use nvme::mi::ResponseStatus;
11+
use nvme::{
12+
AdminGetLogPageLidRequestType, LidSupportedAndEffectsFlags, LogPageAttributes,
13+
mi::ResponseStatus,
14+
};
1215
use uuid::Uuid;
1316

1417
pub mod nvme;
@@ -240,14 +243,14 @@ pub enum Temperature<T> {
240243
}
241244

242245
#[derive(Debug)]
243-
struct OperatingRange {
246+
struct OperatingRange<T> {
244247
kind: UnitKind,
245-
lower: u16,
246-
upper: u16,
248+
lower: T,
249+
upper: T,
247250
}
248251

249-
impl OperatingRange {
250-
fn new(kind: UnitKind, lower: u16, upper: u16) -> Self {
252+
impl<T> OperatingRange<T> {
253+
fn new(kind: UnitKind, lower: T, upper: T) -> Self {
251254
Self { kind, lower, upper }
252255
}
253256
}
@@ -268,15 +271,17 @@ pub struct Controller {
268271
secondaries: heapless::Vec<SecondaryController, 0>,
269272
active_ns: heapless::Vec<NamespaceId, MAX_NAMESPACES>,
270273
temp: u16,
271-
temp_range: OperatingRange,
274+
temp_range: OperatingRange<u16>,
272275
capacity: u64,
273276
spare: u64,
274-
spare_range: OperatingRange,
277+
spare_range: OperatingRange<u64>,
275278
write_age: u64,
276279
write_lifespan: u64,
277280
ro: bool,
278281
cc: nvme::ControllerConfiguration,
279282
csts: FlagSet<nvme::ControllerStatusFlags>,
283+
lpa: FlagSet<LogPageAttributes>,
284+
lsaes: [FlagSet<LidSupportedAndEffectsFlags>; 3],
280285
}
281286

282287
impl Controller {
@@ -296,6 +301,15 @@ impl Controller {
296301
ro: false,
297302
cc: nvme::ControllerConfiguration::default(),
298303
csts: FlagSet::empty(),
304+
lpa: FlagSet::empty(),
305+
lsaes: {
306+
let mut arr = [FlagSet::default(); 3];
307+
arr[AdminGetLogPageLidRequestType::SupportedLogPages.id() as usize] =
308+
LidSupportedAndEffectsFlags::Lsupp.into();
309+
arr[AdminGetLogPageLidRequestType::SmartHealthInformation.id() as usize] =
310+
LidSupportedAndEffectsFlags::Lsupp.into();
311+
arr
312+
},
299313
}
300314
}
301315

src/nvme.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ unsafe impl Discriminant<u8> for AdminIoCqeStatusType {}
106106
#[repr(u8)]
107107
enum AdminIoCqeGenericCommandStatus {
108108
SuccessfulCompletion = 0x00,
109+
InvalidFieldInCommand = 0x02,
109110
}
110111
unsafe impl Discriminant<u8> for AdminIoCqeGenericCommandStatus {}
111112

@@ -152,6 +153,95 @@ pub struct AdminIdentifyNvmIdentifyNamespaceResponse {
152153
}
153154
impl Encode<4096> for AdminIdentifyNvmIdentifyNamespaceResponse {}
154155

156+
// Base v2.1, 5.1.12, Figure 202
157+
// MI v2.0, 6.3, Figure 141
158+
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
159+
#[deku(ctx = "endian: Endian, lid: u8", id = "lid", endian = "endian")]
160+
#[repr(u8)]
161+
pub enum AdminGetLogPageLidRequestType {
162+
SupportedLogPages = 0x00,
163+
ErrorInformation = 0x01,
164+
SmartHealthInformation = 0x02,
165+
FeatureIdentifiersSupportedAndEffects = 0x12,
166+
}
167+
unsafe impl Discriminant<u8> for AdminGetLogPageLidRequestType {}
168+
169+
// Base v2.1, 5.1.12.1.1, Figure 203
170+
#[derive(Debug, DekuRead, DekuWrite)]
171+
#[deku(endian = "little")]
172+
pub struct AdminGetLogPageSupportedLogPagesResponse {
173+
lsids: WireVec<LidSupportedAndEffectsDataStructure, 256>,
174+
}
175+
impl Encode<1024> for AdminGetLogPageSupportedLogPagesResponse {}
176+
177+
// Base v2.1, 5.1.12.1.1, Figure 204
178+
flags! {
179+
pub enum LidSupportedAndEffectsFlags: u8 {
180+
Lsupp,
181+
Ios,
182+
}
183+
}
184+
185+
// Base v2.1, 5.1.12.1.1, Figure 204
186+
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite)]
187+
#[deku(ctx = "endian: Endian", endian = "endian")]
188+
pub struct LidSupportedAndEffectsDataStructure {
189+
flags: WireFlagSet<LidSupportedAndEffectsFlags>,
190+
#[deku(seek_from_current = "1")]
191+
lidsp: u16,
192+
}
193+
194+
// Base v2.1, 5.1.12.1.3, Figure 206, CW
195+
flags! {
196+
pub enum CriticalWarning: u8 {
197+
Ascbt,
198+
Ttc,
199+
Ndr,
200+
Amro,
201+
Vmbf,
202+
Pmrro,
203+
}
204+
}
205+
206+
// Base v2.1, 5.1.12.1.3, Figure 206, EGCWS
207+
flags! {
208+
pub enum EnduranceGroupCriticalWarningSummary: u8 {
209+
Egascbt = 1 << 0,
210+
Egdr = 1 << 2,
211+
Egro = 1 << 3,
212+
}
213+
}
214+
215+
// Base v2.1, 5.1.12.1.3, Figure 206
216+
#[derive(Debug, Default, DekuRead, DekuWrite)]
217+
#[deku(endian = "little")]
218+
pub struct SmartHealthInformationLogPageResponse {
219+
cw: WireFlagSet<CriticalWarning>,
220+
ctemp: u16,
221+
avsp: u8,
222+
avspt: u8,
223+
pused: u8,
224+
egcws: WireFlagSet<EnduranceGroupCriticalWarningSummary>,
225+
#[deku(seek_from_current = "25")]
226+
dur: u128,
227+
duw: u128,
228+
hrc: u128,
229+
hwc: u128,
230+
cbt: u128,
231+
pwrc: u128,
232+
poh: u128,
233+
upl: u128,
234+
mdie: u128,
235+
neile: u128,
236+
wctt: u32,
237+
cctt: u32,
238+
tsen: [u16; 8],
239+
tmttc: [u32; 2],
240+
#[deku(pad_bytes_after = "280")]
241+
tttmt: [u32; 2],
242+
}
243+
impl Encode<512> for SmartHealthInformationLogPageResponse {}
244+
155245
// Base v2.1, 5.1.13.1, Figure 311
156246
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite)]
157247
#[deku(id_type = "u8", endian = "endian", ctx = "endian: Endian")]

src/nvme/mi.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use log::debug;
55

66
use crate::{CommandEffectError, Discriminant, Encode};
77

8-
use super::AdminIdentifyCnsRequestType;
8+
use super::{AdminGetLogPageLidRequestType, AdminIdentifyCnsRequestType};
99

1010
// SPDX-License-Identifier: GPL-3.0-only
1111
/*
@@ -591,7 +591,8 @@ impl Encode<32> for ControllerInformationResponse {}
591591
enum AdminCommandRequestType {
592592
DeleteIoSubmissionQueue = 0x00, // P
593593
CreateIoSubmissionQueue = 0x01, // P
594-
GetLogPage = 0x02, // M
594+
#[deku(id = 0x02)]
595+
GetLogPage(AdminGetLogPageRequest), // M
595596
DeleteIoCompletionQueue = 0x04, // P
596597
CreateIoCompletionQueue = 0x05, // P
597598
#[deku(id = 0x06)]
@@ -634,6 +635,31 @@ struct AdminCommandRequestHeader {
634635
op: AdminCommandRequestType,
635636
}
636637

638+
// MI v2.0, 6, Figure 136
639+
// Base v2.1, 5.1.12, Figures 197-201
640+
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]
641+
#[deku(ctx = "endian: Endian", endian = "endian")]
642+
struct AdminGetLogPageRequest {
643+
nsid: u32,
644+
#[deku(seek_from_current = "16")]
645+
dofst: u32,
646+
dlen: u32,
647+
#[deku(seek_from_current = "8")]
648+
#[deku(update = "self.req.id()")]
649+
lid: u8,
650+
lsp_rae: u8,
651+
numdw: u32, // Synthesised from NUMDL / NUMDU
652+
lsi: u16,
653+
lpo: u64, // Synthesised from LPOL / LPOU
654+
uidx: u8,
655+
#[deku(seek_from_current = "1")]
656+
ot: u8,
657+
csi: u8,
658+
#[deku(pad_bytes_after = "4")]
659+
#[deku(ctx = "*lid")]
660+
req: AdminGetLogPageLidRequestType,
661+
}
662+
637663
// MI v2.0, 6, Figure 136
638664
// Base v2.1, 5.1.13.1, Figures 306-309
639665
#[derive(Debug, DekuRead, DekuWrite, Eq, PartialEq)]

0 commit comments

Comments
 (0)