Skip to content

Commit 0b0df6a

Browse files
committed
nvme: mi: dev: Implement Admin / Get Log Page / Features Identifiers Supported and Effects
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
1 parent 43fd3ab commit 0b0df6a

File tree

4 files changed

+192
-3
lines changed

4 files changed

+192
-3
lines changed

src/lib.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ pub struct Controller {
281281
cc: nvme::ControllerConfiguration,
282282
csts: FlagSet<nvme::ControllerStatusFlags>,
283283
lpa: FlagSet<LogPageAttributes>,
284-
lsaes: [FlagSet<LidSupportedAndEffectsFlags>; 3],
284+
lsaes: [FlagSet<LidSupportedAndEffectsFlags>; 19],
285285
}
286286

287287
impl Controller {
@@ -303,11 +303,13 @@ impl Controller {
303303
csts: FlagSet::empty(),
304304
lpa: FlagSet::empty(),
305305
lsaes: {
306-
let mut arr = [FlagSet::default(); 3];
306+
let mut arr = [FlagSet::default(); 19];
307307
arr[AdminGetLogPageLidRequestType::SupportedLogPages.id() as usize] =
308308
LidSupportedAndEffectsFlags::Lsupp.into();
309309
arr[AdminGetLogPageLidRequestType::SmartHealthInformation.id() as usize] =
310310
LidSupportedAndEffectsFlags::Lsupp.into();
311+
arr[AdminGetLogPageLidRequestType::FeatureIdentifiersSupportedAndEffects.id()
312+
as usize] = LidSupportedAndEffectsFlags::Lsupp.into();
311313
arr
312314
},
313315
}

src/nvme.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,32 @@ pub struct SmartHealthInformationLogPageResponse {
199199
}
200200
impl Encode<512> for SmartHealthInformationLogPageResponse {}
201201

202+
// Base v2.1, 5.1.12.1.18, Figure 262
203+
flags! {
204+
pub enum FidSupportedAndEffectsFlags: u32 {
205+
Fsupp = 1 << 0,
206+
Udcc = 1 << 1,
207+
Ncc = 1 << 2,
208+
Nic = 1 << 3,
209+
Ccc = 1 << 4,
210+
Uss = 1 << 19,
211+
FspNscpe = 1 << 20,
212+
FspCscpe = 1 << 21,
213+
FspNsetscpe = 1 << 22,
214+
FspEgscpe = 1 << 23,
215+
FspDscpe = 1 << 24,
216+
FspNsubscpe = 1 << 25,
217+
FspCdqscp = 1 << 26,
218+
FspMask = (
219+
FidSupportedAndEffectsFlags::FspNscpe
220+
| FidSupportedAndEffectsFlags::FspNsetscpe
221+
| FidSupportedAndEffectsFlags::FspEgscpe
222+
| FidSupportedAndEffectsFlags::FspNsubscpe
223+
| FidSupportedAndEffectsFlags::FspCdqscp
224+
).bits()
225+
}
226+
}
227+
202228
// Base v2.1, 5.1.13.1, Figure 310
203229
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
204230
#[deku(ctx = "endian: Endian, cns: u8", id = "cns", endian = "endian")]
@@ -423,3 +449,12 @@ impl ControllerListResponse {
423449
}
424450
}
425451
}
452+
453+
// Base v2.1, 5.1.25, Figure 385
454+
// Base v2.1, 3.1.3.6, Figure 32
455+
#[derive(Debug, DekuRead, DekuWrite)]
456+
#[deku(ctx = "endian: Endian", endian = "endian", id_type = "u8")]
457+
#[repr(u8)]
458+
pub enum FeatureIdentifiers {
459+
KeepAliveTimer = 0x0f,
460+
}

src/nvme/mi/dev.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1023,7 +1023,21 @@ impl RequestHandler for AdminGetLogPageRequest {
10231023
.await
10241024
}
10251025
AdminGetLogPageLidRequestType::FeatureIdentifiersSupportedAndEffects => {
1026-
todo!()
1026+
if (self.numdw + 1) * 4 != 1024 {
1027+
debug!("Implement support for NUMDL / NUMDU");
1028+
return Err(ResponseStatus::InternalError);
1029+
}
1030+
1031+
admin_send_response_body(
1032+
resp,
1033+
admin_constrain_body(
1034+
self.dofst,
1035+
self.dlen,
1036+
// TODO: Support feature reporting
1037+
&[0u8; 1024],
1038+
)?,
1039+
)
1040+
.await
10271041
}
10281042
}
10291043
}

tests/admin.rs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2317,4 +2317,142 @@ mod get_log_page {
23172317
.await
23182318
});
23192319
}
2320+
2321+
#[test]
2322+
fn feature_identifiers_supported_and_effects_short() {
2323+
setup();
2324+
2325+
let (mut mep, mut subsys) = new_device(DeviceType::P1p1tC1aN0a0a);
2326+
2327+
#[rustfmt::skip]
2328+
const REQ: [u8; 67] = [
2329+
0x10, 0x00, 0x00,
2330+
0x02, 0x00, 0x00, 0x00,
2331+
2332+
// SQE DWORD 1
2333+
0x00, 0x00, 0x00, 0x00,
2334+
0x00, 0x00, 0x00, 0x00,
2335+
0x00, 0x00, 0x00, 0x00,
2336+
0x00, 0x00, 0x00, 0x00,
2337+
0x00, 0x00, 0x00, 0x00,
2338+
2339+
// DOFST
2340+
0x00, 0x00, 0x00, 0x00,
2341+
0x00, 0x04, 0x00, 0x00,
2342+
2343+
// Reserved
2344+
0x00, 0x00, 0x00, 0x00,
2345+
0x00, 0x00, 0x00, 0x00,
2346+
2347+
// SQE DWORD 10
2348+
0x12, 0x00, 0xff, 0x00,
2349+
0x00, 0x00, 0x00, 0x00,
2350+
0x00, 0x00, 0x00, 0x00,
2351+
0x00, 0x00, 0x00, 0x00,
2352+
0x00, 0x00, 0x00, 0x00,
2353+
// Missing SQE DWORD 15
2354+
2355+
// MIC
2356+
0xfa, 0x21, 0x62, 0x5f
2357+
];
2358+
2359+
let resp = ExpectedRespChannel::new(&RESP_INVALID_COMMAND_SIZE);
2360+
smol::block_on(async {
2361+
mep.handle_async(&mut subsys, &REQ, MsgIC(true), resp, async |_| Ok(()))
2362+
.await
2363+
});
2364+
}
2365+
2366+
#[test]
2367+
fn feature_identifiers_supported_and_effects_long() {
2368+
setup();
2369+
2370+
let (mut mep, mut subsys) = new_device(DeviceType::P1p1tC1aN0a0a);
2371+
2372+
#[rustfmt::skip]
2373+
const REQ: [u8; 75] = [
2374+
0x10, 0x00, 0x00,
2375+
0x02, 0x00, 0x00, 0x00,
2376+
2377+
// SQE DWORD 1
2378+
0x00, 0x00, 0x00, 0x00,
2379+
0x00, 0x00, 0x00, 0x00,
2380+
0x00, 0x00, 0x00, 0x00,
2381+
0x00, 0x00, 0x00, 0x00,
2382+
0x00, 0x00, 0x00, 0x00,
2383+
2384+
// DOFST
2385+
0x00, 0x00, 0x00, 0x00,
2386+
0x00, 0x04, 0x00, 0x00,
2387+
2388+
// Reserved
2389+
0x00, 0x00, 0x00, 0x00,
2390+
0x00, 0x00, 0x00, 0x00,
2391+
2392+
// SQE DWORD 10
2393+
0x12, 0x00, 0xff, 0x00,
2394+
0x00, 0x00, 0x00, 0x00,
2395+
0x00, 0x00, 0x00, 0x00,
2396+
0x00, 0x00, 0x00, 0x00,
2397+
0x00, 0x00, 0x00, 0x00,
2398+
0x00, 0x00, 0x00, 0x00,
2399+
0x00, 0x00, 0x00, 0x00,
2400+
2401+
// MIC
2402+
0x1d, 0x31, 0x5a, 0x2b
2403+
];
2404+
2405+
let resp = ExpectedRespChannel::new(&RESP_INVALID_COMMAND_SIZE);
2406+
smol::block_on(async {
2407+
mep.handle_async(&mut subsys, &REQ, MsgIC(true), resp, async |_| Ok(()))
2408+
.await
2409+
});
2410+
}
2411+
2412+
#[test]
2413+
fn feature_identifiers_supported_and_effects() {
2414+
setup();
2415+
2416+
let (mut mep, mut subsys) = new_device(DeviceType::P1p1tC1aN0a0a);
2417+
2418+
#[rustfmt::skip]
2419+
const REQ: [u8; 71] = [
2420+
0x10, 0x00, 0x00,
2421+
0x02, 0x00, 0x00, 0x00,
2422+
2423+
// SQE DWORD 1
2424+
0x00, 0x00, 0x00, 0x00,
2425+
0x00, 0x00, 0x00, 0x00,
2426+
0x00, 0x00, 0x00, 0x00,
2427+
0x00, 0x00, 0x00, 0x00,
2428+
0x00, 0x00, 0x00, 0x00,
2429+
2430+
// DOFST
2431+
0x00, 0x00, 0x00, 0x00,
2432+
0x00, 0x04, 0x00, 0x00,
2433+
2434+
// Reserved
2435+
0x00, 0x00, 0x00, 0x00,
2436+
0x00, 0x00, 0x00, 0x00,
2437+
2438+
// SQE DWORD 10
2439+
0x12, 0x00, 0xff, 0x00,
2440+
0x00, 0x00, 0x00, 0x00,
2441+
0x00, 0x00, 0x00, 0x00,
2442+
0x00, 0x00, 0x00, 0x00,
2443+
0x00, 0x00, 0x00, 0x00,
2444+
0x00, 0x00, 0x00, 0x00,
2445+
2446+
// MIC
2447+
0xbb, 0xa2, 0xe9, 0x2a
2448+
];
2449+
2450+
let resp_fields: Vec<ExpectedField> = vec![(0, &[0x90]), (15, &[0x00, 0x00, 0x01, 0x00])];
2451+
2452+
let resp = RelaxedRespChannel::new(resp_fields);
2453+
smol::block_on(async {
2454+
mep.handle_async(&mut subsys, &REQ, MsgIC(true), resp, async |_| Ok(()))
2455+
.await
2456+
});
2457+
}
23202458
}

0 commit comments

Comments
 (0)