Skip to content

Commit a62256b

Browse files
committed
nvme: mi: dev: Effect for NVMe MI / Configuration Set / SMBus Frequency
Signed-off-by: Andrew Jeffery <andrew@codeconstruct.com.au>
1 parent 03363af commit a62256b

File tree

4 files changed

+104
-16
lines changed

4 files changed

+104
-16
lines changed

src/lib.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,14 @@ const MAX_NIDTS: usize = 2;
2323

2424
#[derive(Debug)]
2525
pub enum CommandEffect {
26-
SetMtu { port_id: PortId, mtus: usize },
26+
SetMtu {
27+
port_id: PortId,
28+
mtus: usize,
29+
},
30+
SetSmbusFreq {
31+
port_id: PortId,
32+
freq: nvme::mi::SmbusFrequency,
33+
},
2734
}
2835

2936
#[derive(Debug)]
@@ -101,12 +108,15 @@ impl Default for PciePort {
101108

102109
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
103110
pub struct TwoWirePort {
111+
// MI v2.0, 5.7.2, Figure 116
104112
cvpdaddr: u8,
105113
mvpdfreq: nvme::mi::SmbusFrequency,
106114
cmeaddr: u8,
107115
i3csprt: bool,
108116
msmbfreq: nvme::mi::SmbusFrequency,
109117
nvmebms: bool,
118+
// Local state
119+
smbfreq: nvme::mi::SmbusFrequency,
110120
}
111121

112122
impl TwoWirePort {
@@ -116,8 +126,9 @@ impl TwoWirePort {
116126
mvpdfreq: nvme::mi::SmbusFrequency::FreqNotSupported,
117127
cmeaddr: 0x1d,
118128
i3csprt: false,
119-
msmbfreq: nvme::mi::SmbusFrequency::Freq100Khz,
129+
msmbfreq: nvme::mi::SmbusFrequency::Freq400Khz,
120130
nvmebms: false,
131+
smbfreq: nvme::mi::SmbusFrequency::Freq100Khz,
121132
}
122133
}
123134
}

src/nvme/mi.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ impl Encode<24> for PciePortDataResponse {}
544544

545545
// MI v2.0, Figure 116, MVPDFREQ
546546
#[allow(dead_code)]
547-
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, PartialEq)]
547+
#[derive(Clone, Copy, Debug, DekuRead, DekuWrite, Eq, Ord, PartialEq, PartialOrd)]
548548
#[deku(endian = "endian", ctx = "endian: Endian")]
549549
#[deku(id_type = "u8")]
550550
#[repr(u8)]

src/nvme/mi/dev.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -269,23 +269,28 @@ impl RequestHandler for NvmeMiConfigurationSetRequest {
269269
return Err(ResponseStatus::InvalidCommandSize);
270270
}
271271

272-
let Some(port) = subsys.ports.get(sifr.dw0_portid as usize) else {
272+
let Some(port) = subsys.ports.get_mut(sifr.dw0_portid as usize) else {
273273
debug!("Unrecognised port ID: {}", sifr.dw0_portid);
274274
return Err(ResponseStatus::InvalidParameter);
275275
};
276276

277-
let crate::PortType::TwoWire(twprt) = port.typ else {
277+
let crate::PortType::TwoWire(twprt) = &mut port.typ else {
278278
debug!("Port {} is not a TwoWire port: {:?}", sifr.dw0_portid, port);
279279
return Err(ResponseStatus::InvalidParameter);
280280
};
281281

282-
if sifr.dw0_sfreq != crate::nvme::mi::SmbusFrequency::Freq100Khz {
283-
if twprt.msmbfreq != super::SmbusFrequency::Freq100Khz {
284-
todo!("Maintain port state and configure the hardware");
285-
}
282+
if sifr.dw0_sfreq > twprt.msmbfreq {
283+
debug!("Unsupported SMBus frequency: {:?}", sifr.dw0_sfreq);
286284
return Err(ResponseStatus::InvalidParameter);
287285
}
288286

287+
app(CommandEffect::SetSmbusFreq {
288+
port_id: port.id,
289+
freq: sifr.dw0_sfreq,
290+
})
291+
.await?;
292+
twprt.smbfreq = sifr.dw0_sfreq;
293+
289294
let mh = MessageHeader::respond(MessageType::NvmeMiCommand).encode()?;
290295

291296
// Success
@@ -391,7 +396,7 @@ impl RequestHandler for NvmeMiConfigurationGetRequest {
391396

392397
let fr = GetSmbusI2cFrequencyResponse {
393398
status: ResponseStatus::Success,
394-
mr_sfreq: twprt.msmbfreq,
399+
mr_sfreq: twprt.smbfreq,
395400
}
396401
.encode()?;
397402

tests/nvme_mi.rs

Lines changed: 78 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -231,13 +231,13 @@ mod read_nvme_mi_data_structure {
231231
0x00, 0x20, 0x00, 0x00,
232232
0x02, 0x00, 0x40, 0x00,
233233
0x00, 0x00, 0x00, 0x00,
234-
0x00, 0x00, 0x1d, 0x01,
234+
0x00, 0x00, 0x1d, 0x02,
235235
0x00, 0x00, 0x00, 0x00,
236236
0x00, 0x00, 0x00, 0x00,
237237
0x00, 0x00, 0x00, 0x00,
238238
0x00, 0x00, 0x00, 0x00,
239239
0x00, 0x00, 0x00, 0x00,
240-
0xc4, 0x05, 0xbc, 0x27
240+
0xf3, 0x83, 0xa2, 0x30
241241
];
242242

243243
let resp = ExpectedRespChannel::new(&RESP);
@@ -1232,9 +1232,9 @@ mod configuration_set {
12321232
const REQ: [u8; 19] = [
12331233
0x08, 0x00, 0x00,
12341234
0x03, 0x00, 0x00, 0x00,
1235-
0x01, 0x02, 0x00, 0x01,
1235+
0x01, 0x03, 0x00, 0x01,
12361236
0x00, 0x00, 0x00, 0x00,
1237-
0xa9, 0x37, 0xbf, 0xf5
1237+
0x61, 0x1b, 0xbc, 0x9d
12381238
];
12391239

12401240
let resp = ExpectedRespChannel::new(&RESP_INVALID_PARAMETER);
@@ -1245,7 +1245,7 @@ mod configuration_set {
12451245
}
12461246

12471247
#[test]
1248-
fn smbus_i2c_frequency_supported() {
1248+
fn smbus_i2c_frequency_supported_effect_failure() {
12491249
setup();
12501250

12511251
let (mut mep, mut subsys) = new_device(DeviceType::P1p1tC1aN0a0a);
@@ -1259,11 +1259,83 @@ mod configuration_set {
12591259
0xf1, 0x42, 0xba, 0x4d
12601260
];
12611261

1262+
let resp = ExpectedRespChannel::new(&RESP_INTERNAL_ERROR);
1263+
smol::block_on(async {
1264+
mep.handle_async(&mut subsys, &REQ, MsgIC(true), resp, async |_| {
1265+
Err(CommandEffectError::InternalError)
1266+
})
1267+
.await
1268+
});
1269+
}
1270+
1271+
#[test]
1272+
fn smbus_i2c_frequency_supported() {
1273+
setup();
1274+
1275+
let (mut mep, mut subsys) = new_device(DeviceType::P1p1tC1aN0a0a);
1276+
1277+
#[rustfmt::skip]
1278+
const REQ_GET_INIT: [u8; 19] = [
1279+
0x08, 0x00, 0x00,
1280+
0x04, 0x00, 0x00, 0x00,
1281+
0x01, 0x00, 0x00, 0x01,
1282+
0x00, 0x00, 0x00, 0x00,
1283+
0xa9, 0x42, 0xec, 0xb3
1284+
];
1285+
1286+
#[rustfmt::skip]
1287+
const RESP_GET_INIT: [u8; 11] = [
1288+
0x88, 0x00, 0x00,
1289+
0x00, 0x01, 0x00, 0x00,
1290+
0x5a, 0xc7, 0x36, 0x87
1291+
];
1292+
1293+
let resp = ExpectedRespChannel::new(&RESP_GET_INIT);
1294+
smol::block_on(async {
1295+
mep.handle_async(&mut subsys, &REQ_GET_INIT, MsgIC(true), resp, async |_| {
1296+
Ok(())
1297+
})
1298+
.await
1299+
});
1300+
1301+
#[rustfmt::skip]
1302+
const REQ_SET: [u8; 19] = [
1303+
0x08, 0x00, 0x00,
1304+
0x03, 0x00, 0x00, 0x00,
1305+
0x01, 0x02, 0x00, 0x01,
1306+
0x00, 0x00, 0x00, 0x00,
1307+
0xa9, 0x37, 0xbf, 0xf5
1308+
];
1309+
12621310
let resp = ExpectedRespChannel::new(&RESP_SUCCESS);
12631311
smol::block_on(async {
1264-
mep.handle_async(&mut subsys, &REQ, MsgIC(true), resp, async |_| Ok(()))
1312+
mep.handle_async(&mut subsys, &REQ_SET, MsgIC(true), resp, async |_| Ok(()))
12651313
.await
12661314
});
1315+
1316+
#[rustfmt::skip]
1317+
const REQ_GET_NEW: [u8; 19] = [
1318+
0x08, 0x00, 0x00,
1319+
0x04, 0x00, 0x00, 0x00,
1320+
0x01, 0x00, 0x00, 0x01,
1321+
0x00, 0x00, 0x00, 0x00,
1322+
0xa9, 0x42, 0xec, 0xb3
1323+
];
1324+
1325+
#[rustfmt::skip]
1326+
const RESP_GET_NEW: [u8; 11] = [
1327+
0x88, 0x00, 0x00,
1328+
0x00, 0x02, 0x00, 0x00,
1329+
0x29, 0x07, 0x18, 0x6d
1330+
];
1331+
1332+
let resp = ExpectedRespChannel::new(&RESP_GET_NEW);
1333+
smol::block_on(async {
1334+
mep.handle_async(&mut subsys, &REQ_GET_NEW, MsgIC(true), resp, async |_| {
1335+
Ok(())
1336+
})
1337+
.await
1338+
});
12671339
}
12681340

12691341
#[test]

0 commit comments

Comments
 (0)