pcics/extended_capabilities/latency_tolerance_reporting.rs
1/*!
2# Latency Tolerance Reporting (LTR)
3
4The PCI Express Latency Tolerance Reporting (LTR) Capability is an optional Extended Capability
5that allows software to provide platform latency information to components with Upstream Ports
6(Endpoints and Switches), and is required for Switch Upstream Ports and Endpoints if the
7Function supports the LTR mechanism. It is not applicable to Root Ports, Bridges, or Switch
8Downstream Ports.
9
10## Struct diagram
11[LatencyToleranceReporting]
12
13## Examples
14> ```text
15> Max snoop latency: 71680ns
16> Max no snoop latency: 71680ns
17> ```
18
19```rust
20# use pcics::extended_capabilities::latency_tolerance_reporting::*;
21let data = [
22 0x18, 0x00, 0x01, 0x1d, 0x46, 0x08, 0x46, 0x08,
23];
24let result = data[4..].try_into().unwrap();
25let sample = LatencyToleranceReporting {
26 max_snoop_latency: MaxLatency { value: 70, scale: 2 },
27 max_no_snoop_latency: MaxLatency { value: 70, scale: 2 },
28};
29assert_eq!(sample, result);
30```
31*/
32
33use heterob::{bit_numbering::Lsb, endianness::Le, Seq, P2, P3};
34
35use super::ExtendedCapabilityDataError;
36
37#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct LatencyToleranceReporting {
39 /// Max Snoop Latency
40 pub max_snoop_latency: MaxLatency,
41 /// Max No-Snoop Latency
42 pub max_no_snoop_latency: MaxLatency,
43}
44impl TryFrom<&[u8]> for LatencyToleranceReporting {
45 type Error = ExtendedCapabilityDataError;
46
47 fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
48 let Seq {
49 head: Le((max_snoop_latency, max_no_snoop_latency)),
50 ..
51 } = P2(slice)
52 .try_into()
53 .map_err(|_| ExtendedCapabilityDataError {
54 name: "Latency Tolerance Reporting",
55 size: 8,
56 })?;
57 Ok(Self {
58 max_snoop_latency: From::<u16>::from(max_snoop_latency),
59 max_no_snoop_latency: From::<u16>::from(max_no_snoop_latency),
60 })
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Eq)]
65pub struct MaxLatency {
66 /// Specifies the maximum latency that a device is permitted to request
67 pub value: u16,
68 /// Provides a scale for the value contained within the value field
69 pub scale: u8,
70}
71impl MaxLatency {
72 pub fn value(&self) -> usize {
73 match self.scale {
74 scale @ 0..=5 => (self.value as usize) << (5 * scale),
75 _ => 0,
76 }
77 }
78}
79
80impl From<u16> for MaxLatency {
81 fn from(word: u16) -> Self {
82 let Lsb((value, scale, ())) = P3::<_, 10, 3, 3>(word).into();
83 Self { value, scale }
84 }
85}
86
87impl From<MaxLatency> for u16 {
88 fn from(data: MaxLatency) -> Self {
89 (data.scale as u16) << 13 | data.value
90 }
91}