devices/usb/xhci/
interrupter.rs1use std::time::Duration;
6use std::time::Instant;
7
8use base::Clock;
9use base::Error as SysError;
10use base::Event;
11use remain::sorted;
12use thiserror::Error;
13use vm_memory::GuestAddress;
14use vm_memory::GuestMemory;
15
16use super::event_ring::Error as EventRingError;
17use super::event_ring::EventRing;
18use super::xhci_abi::CommandCompletionEventTrb;
19use super::xhci_abi::Error as TrbError;
20use super::xhci_abi::PortStatusChangeEventTrb;
21use super::xhci_abi::TransferEventTrb;
22use super::xhci_abi::Trb;
23use super::xhci_abi::TrbCast;
24use super::xhci_abi::TrbCompletionCode;
25use super::xhci_abi::TrbType;
26use super::xhci_regs::XhciRegs;
27use super::xhci_regs::ERDP_EVENT_HANDLER_BUSY;
28use super::xhci_regs::IMAN_INTERRUPT_PENDING;
29use super::xhci_regs::USB_STS_EVENT_INTERRUPT;
30use crate::register_space::Register;
31
32#[sorted]
33#[derive(Error, Debug)]
34pub enum Error {
35 #[error("cannot add event: {0}")]
36 AddEvent(EventRingError),
37 #[error("cannot cast trb: {0}")]
38 CastTrb(TrbError),
39 #[error("cannot send interrupt: {0}")]
40 SendInterrupt(SysError),
41 #[error("cannot set seg table base addr: {0}")]
42 SetSegTableBaseAddr(EventRingError),
43 #[error("cannot set seg table size: {0}")]
44 SetSegTableSize(EventRingError),
45}
46
47type Result<T> = std::result::Result<T, Error>;
48
49pub struct Interrupter {
52 interrupt_evt: Event,
53 usbsts: Register<u32>,
54 iman: Register<u32>,
55 erdp: Register<u64>,
56 event_handler_busy: bool,
57 enabled: bool,
58 moderation_interval: u16,
59 moderation_counter: u16,
60 event_ring: EventRing,
61 last_interrupt_time: Instant,
62 clock: Clock,
63}
64
65impl Interrupter {
66 pub fn new(mem: GuestMemory, irq_evt: Event, regs: &XhciRegs) -> Self {
68 let clock = Clock::new();
69 Interrupter {
70 interrupt_evt: irq_evt,
71 usbsts: regs.usbsts.clone(),
72 iman: regs.iman.clone(),
73 erdp: regs.erdp.clone(),
74 event_handler_busy: false,
75 enabled: false,
76 moderation_interval: 4000, moderation_counter: 0, event_ring: EventRing::new(mem),
79 last_interrupt_time: clock.now(),
80 clock,
81 }
82 }
83
84 pub fn event_ring_is_empty(&self) -> bool {
86 self.event_ring.is_empty()
87 }
88
89 fn add_event(&mut self, trb: Trb) -> Result<()> {
91 self.event_ring.add_event(trb).map_err(Error::AddEvent)?;
92 self.interrupt_if_needed()
93 }
94
95 pub fn send_port_status_change_trb(&mut self, port_id: u8) -> Result<()> {
97 let mut trb = Trb::new();
98 let psctrb = trb
99 .cast_mut::<PortStatusChangeEventTrb>()
100 .map_err(Error::CastTrb)?;
101 psctrb.set_port_id(port_id);
102 psctrb.set_completion_code(TrbCompletionCode::Success);
103 psctrb.set_trb_type(TrbType::PortStatusChangeEvent);
104 self.add_event(trb)
105 }
106
107 pub fn send_command_completion_trb(
109 &mut self,
110 completion_code: TrbCompletionCode,
111 slot_id: u8,
112 trb_addr: GuestAddress,
113 ) -> Result<()> {
114 let mut trb = Trb::new();
115 let ctrb = trb
116 .cast_mut::<CommandCompletionEventTrb>()
117 .map_err(Error::CastTrb)?;
118 ctrb.set_trb_pointer(trb_addr.0);
119 ctrb.set_command_completion_parameter(0);
120 ctrb.set_completion_code(completion_code);
121 ctrb.set_trb_type(TrbType::CommandCompletionEvent);
122 ctrb.set_vf_id(0);
123 ctrb.set_slot_id(slot_id);
124 self.add_event(trb)
125 }
126
127 pub fn send_transfer_event_trb(
129 &mut self,
130 completion_code: TrbCompletionCode,
131 trb_pointer: u64,
132 transfer_length: u32,
133 event_data: bool,
134 slot_id: u8,
135 endpoint_id: u8,
136 ) -> Result<()> {
137 let mut trb = Trb::new();
138 let event_trb = trb.cast_mut::<TransferEventTrb>().map_err(Error::CastTrb)?;
139 event_trb.set_trb_pointer(trb_pointer);
140 event_trb.set_trb_transfer_length(transfer_length);
141 event_trb.set_completion_code(completion_code);
142 event_trb.set_event_data(event_data.into());
143 event_trb.set_trb_type(TrbType::TransferEvent);
144 event_trb.set_endpoint_id(endpoint_id);
145 event_trb.set_slot_id(slot_id);
146 self.add_event(trb)
147 }
148
149 pub fn set_enabled(&mut self, enabled: bool) -> Result<()> {
151 xhci_trace!("interrupter set_enabled({})", enabled);
152 self.enabled = enabled;
153 self.interrupt_if_needed()
154 }
155
156 pub fn set_moderation(&mut self, interval: u16, counter: u16) -> Result<()> {
158 xhci_trace!("interrupter set_moderation({}, {})", interval, counter);
159 self.moderation_interval = interval;
160 self.moderation_counter = counter;
161 self.interrupt_if_needed()
162 }
163
164 pub fn set_event_ring_seg_table_size(&mut self, size: u16) -> Result<()> {
166 xhci_trace!("interrupter set_event_ring_seg_table_size({})", size);
167 self.event_ring
168 .set_seg_table_size(size)
169 .map_err(Error::SetSegTableSize)
170 }
171
172 pub fn set_event_ring_seg_table_base_addr(&mut self, addr: GuestAddress) -> Result<()> {
174 xhci_trace!("interrupter set_table_base_addr({:#x})", addr.0);
175 self.event_ring
176 .set_seg_table_base_addr(addr)
177 .map_err(Error::SetSegTableBaseAddr)
178 }
179
180 pub fn set_event_ring_dequeue_pointer(&mut self, addr: GuestAddress, busy: bool) -> Result<()> {
182 xhci_trace!(
183 "interrupter set_dequeue_pointer(addr = {:#x}, busy = {})",
184 addr.0,
185 busy
186 );
187 self.event_ring.set_dequeue_pointer(addr);
188 self.event_handler_busy = busy;
189 self.interrupt_if_needed()
190 }
191
192 pub fn interrupt(&mut self) -> Result<()> {
194 self.event_handler_busy = true;
195 self.usbsts.set_bits(USB_STS_EVENT_INTERRUPT);
196 self.iman.set_bits(IMAN_INTERRUPT_PENDING);
197 self.erdp.set_bits(ERDP_EVENT_HANDLER_BUSY);
198 self.moderation_counter = self.moderation_interval;
199 self.last_interrupt_time = self.clock.now();
200 self.interrupt_evt.signal().map_err(Error::SendInterrupt)
201 }
202
203 fn interrupt_interval(&self) -> Duration {
204 Duration::new(0, 250 * u32::from(self.moderation_counter))
209 }
210
211 fn interrupt_if_needed(&mut self) -> Result<()> {
212 let can_interrupt = self.last_interrupt_time.elapsed() >= self.interrupt_interval();
213 if self.enabled && can_interrupt && !self.event_ring.is_empty() && !self.event_handler_busy
214 {
215 self.interrupt()?;
216 }
217 Ok(())
218 }
219}