• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 use super::command_ring_controller::{CommandRingController, CommandRingControllerError};
6 use super::device_slot::{DeviceSlots, Error as DeviceSlotError};
7 use super::interrupter::{Error as InterrupterError, Interrupter};
8 use super::intr_resample_handler::IntrResampleHandler;
9 use super::ring_buffer_stop_cb::RingBufferStopCallback;
10 use super::usb_hub::UsbHub;
11 use super::xhci_backend_device_provider::XhciBackendDeviceProvider;
12 use super::xhci_regs::*;
13 use crate::usb::host_backend::host_backend_device_provider::HostBackendDeviceProvider;
14 use crate::utils::{Error as UtilsError, EventLoop, FailHandle};
15 use std::fmt::{self, Display};
16 use std::sync::Arc;
17 use sync::Mutex;
18 use sys_util::{error, EventFd, GuestAddress, GuestMemory};
19 
20 #[derive(Debug)]
21 pub enum Error {
22     StartEventLoop(UtilsError),
23     GetDeviceSlot(u8),
24     StartResampleHandler,
25     SendInterrupt(InterrupterError),
26     EnableInterrupter(InterrupterError),
27     SetModeration(InterrupterError),
28     SetupEventRing(InterrupterError),
29     SetEventHandlerBusy(InterrupterError),
30     StartProvider,
31     RingDoorbell(DeviceSlotError),
32     CreateCommandRingController(CommandRingControllerError),
33     ResetPort,
34 }
35 
36 type Result<T> = std::result::Result<T, Error>;
37 
38 impl Display for Error {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result39     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40         use self::Error::*;
41 
42         match self {
43             StartEventLoop(e) => write!(f, "failed to start event loop: {}", e),
44             GetDeviceSlot(i) => write!(f, "failed to get device slot: {}", i),
45             StartResampleHandler => write!(f, "failed to start resample handler"),
46             SendInterrupt(e) => write!(f, "failed to send interrupter: {}", e),
47             EnableInterrupter(e) => write!(f, "failed to enable interrupter: {}", e),
48             SetModeration(e) => write!(f, "failed to set interrupter moderation: {}", e),
49             SetupEventRing(e) => write!(f, "failed to setup event ring: {}", e),
50             SetEventHandlerBusy(e) => write!(f, "failed to set event handler busy: {}", e),
51             StartProvider => write!(f, "failed to start backend provider"),
52             RingDoorbell(e) => write!(f, "failed to ring doorbell: {}", e),
53             CreateCommandRingController(e) => {
54                 write!(f, "failed to create command ring controller: {}", e)
55             }
56             ResetPort => write!(f, "failed to reset port"),
57         }
58     }
59 }
60 
61 /// xHCI controller implementation.
62 pub struct Xhci {
63     fail_handle: Arc<dyn FailHandle>,
64     regs: XhciRegs,
65     interrupter: Arc<Mutex<Interrupter>>,
66     command_ring_controller: Arc<CommandRingController>,
67     device_slots: DeviceSlots,
68     // resample handler and device provider only lives on EventLoop to handle corresponding events.
69     // By design, event loop only hold weak reference. We need to keep a strong reference here to
70     // keep it alive.
71     #[allow(dead_code)]
72     intr_resample_handler: Arc<IntrResampleHandler>,
73     #[allow(dead_code)]
74     device_provider: HostBackendDeviceProvider,
75 }
76 
77 impl Xhci {
78     /// Create a new xHCI controller.
new( fail_handle: Arc<dyn FailHandle>, mem: GuestMemory, device_provider: HostBackendDeviceProvider, irq_evt: EventFd, irq_resample_evt: EventFd, regs: XhciRegs, ) -> Result<Arc<Self>>79     pub fn new(
80         fail_handle: Arc<dyn FailHandle>,
81         mem: GuestMemory,
82         device_provider: HostBackendDeviceProvider,
83         irq_evt: EventFd,
84         irq_resample_evt: EventFd,
85         regs: XhciRegs,
86     ) -> Result<Arc<Self>> {
87         let (event_loop, _join_handle) =
88             EventLoop::start("xhci".to_string(), Some(fail_handle.clone()))
89                 .map_err(Error::StartEventLoop)?;
90         let interrupter = Arc::new(Mutex::new(Interrupter::new(mem.clone(), irq_evt, &regs)));
91         let event_loop = Arc::new(event_loop);
92         let intr_resample_handler =
93             IntrResampleHandler::start(&event_loop, interrupter.clone(), irq_resample_evt)
94                 .ok_or(Error::StartResampleHandler)?;
95         let hub = Arc::new(UsbHub::new(&regs, interrupter.clone()));
96 
97         let mut device_provider = device_provider;
98         device_provider
99             .start(fail_handle.clone(), event_loop.clone(), hub.clone())
100             .map_err(|_| Error::StartProvider)?;
101 
102         let device_slots = DeviceSlots::new(
103             fail_handle.clone(),
104             regs.dcbaap.clone(),
105             hub.clone(),
106             interrupter.clone(),
107             event_loop.clone(),
108             mem.clone(),
109         );
110         let command_ring_controller = CommandRingController::new(
111             mem.clone(),
112             event_loop.clone(),
113             device_slots.clone(),
114             interrupter.clone(),
115         )
116         .map_err(Error::CreateCommandRingController)?;
117         let xhci = Arc::new(Xhci {
118             fail_handle,
119             regs,
120             intr_resample_handler,
121             interrupter,
122             command_ring_controller,
123             device_slots,
124             device_provider,
125         });
126         Self::init_reg_callbacks(&xhci);
127         Ok(xhci)
128     }
129 
init_reg_callbacks(xhci: &Arc<Xhci>)130     fn init_reg_callbacks(xhci: &Arc<Xhci>) {
131         // All the callbacks will hold a weak reference to avoid memory leak. Thos weak upgrade
132         // should never fail.
133         let xhci_weak = Arc::downgrade(xhci);
134         xhci.regs.usbcmd.set_write_cb(move |val: u32| {
135             // All the weak reference upgrade should never fail. xhci hold reference to the
136             // registers, callback won't be invoked if xhci is gone.
137             let xhci = xhci_weak.upgrade().unwrap();
138             let r = xhci.usbcmd_callback(val);
139             xhci.handle_register_callback_result(r, 0)
140         });
141 
142         let xhci_weak = Arc::downgrade(xhci);
143         xhci.regs.crcr.set_write_cb(move |val: u64| {
144             let xhci = xhci_weak.upgrade().unwrap();
145             let r = xhci.crcr_callback(val);
146             xhci.handle_register_callback_result(r, 0)
147         });
148 
149         for i in 0..xhci.regs.portsc.len() {
150             let xhci_weak = Arc::downgrade(xhci);
151             xhci.regs.portsc[i].set_write_cb(move |val: u32| {
152                 let xhci = xhci_weak.upgrade().unwrap();
153                 let r = xhci.portsc_callback(i as u32, val);
154                 xhci.handle_register_callback_result(r, 0)
155             });
156         }
157 
158         for i in 0..xhci.regs.doorbells.len() {
159             let xhci_weak = Arc::downgrade(xhci);
160             xhci.regs.doorbells[i].set_write_cb(move |val: u32| {
161                 let xhci = xhci_weak.upgrade().unwrap();
162                 let r = xhci.doorbell_callback(i as u32, val);
163                 xhci.handle_register_callback_result(r, ());
164                 val
165             });
166         }
167 
168         let xhci_weak = Arc::downgrade(xhci);
169         xhci.regs.iman.set_write_cb(move |val: u32| {
170             let xhci = xhci_weak.upgrade().unwrap();
171             let r = xhci.iman_callback(val);
172             xhci.handle_register_callback_result(r, ());
173             val
174         });
175 
176         let xhci_weak = Arc::downgrade(xhci);
177         xhci.regs.imod.set_write_cb(move |val: u32| {
178             let xhci = xhci_weak.upgrade().unwrap();
179             let r = xhci.imod_callback(val);
180             xhci.handle_register_callback_result(r, ());
181             val
182         });
183 
184         let xhci_weak = Arc::downgrade(xhci);
185         xhci.regs.erstsz.set_write_cb(move |val: u32| {
186             let xhci = xhci_weak.upgrade().unwrap();
187             let r = xhci.erstsz_callback(val);
188             xhci.handle_register_callback_result(r, ());
189             val
190         });
191 
192         let xhci_weak = Arc::downgrade(xhci);
193         xhci.regs.erstba.set_write_cb(move |val: u64| {
194             let xhci = xhci_weak.upgrade().unwrap();
195             let r = xhci.erstba_callback(val);
196             xhci.handle_register_callback_result(r, ());
197             val
198         });
199 
200         let xhci_weak = Arc::downgrade(xhci);
201         xhci.regs.erdp.set_write_cb(move |val: u64| {
202             let xhci = xhci_weak.upgrade().unwrap();
203             let r = xhci.erdp_callback(val);
204             xhci.handle_register_callback_result(r, ());
205             val
206         });
207     }
208 
handle_register_callback_result<T>(&self, r: Result<T>, t: T) -> T209     fn handle_register_callback_result<T>(&self, r: Result<T>, t: T) -> T {
210         match r {
211             Ok(v) => v,
212             Err(e) => {
213                 error!("xhci controller failed: {}", e);
214                 self.fail_handle.fail();
215                 t
216             }
217         }
218     }
219 
220     // Callback for usbcmd register write.
usbcmd_callback(&self, value: u32) -> Result<u32>221     fn usbcmd_callback(&self, value: u32) -> Result<u32> {
222         if (value & USB_CMD_RESET) > 0 {
223             usb_debug!("xhci_controller: reset controller");
224             self.reset()?;
225             return Ok(value & (!USB_CMD_RESET));
226         }
227 
228         if (value & USB_CMD_RUNSTOP) > 0 {
229             usb_debug!("xhci_controller: clear halt bits");
230             self.regs.usbsts.clear_bits(USB_STS_HALTED);
231         } else {
232             usb_debug!("xhci_controller: halt device");
233             self.halt()?;
234             self.regs.crcr.clear_bits(CRCR_COMMAND_RING_RUNNING);
235         }
236 
237         // Enable interrupter if needed.
238         let enabled = (value & USB_CMD_INTERRUPTER_ENABLE) > 0
239             && (self.regs.iman.get_value() & IMAN_INTERRUPT_ENABLE) > 0;
240         usb_debug!("xhci_controller: interrupter enable?: {}", enabled);
241         self.interrupter
242             .lock()
243             .set_enabled(enabled)
244             .map_err(Error::EnableInterrupter)?;
245         Ok(value)
246     }
247 
248     // Callback for crcr register write.
crcr_callback(&self, value: u64) -> Result<u64>249     fn crcr_callback(&self, value: u64) -> Result<u64> {
250         usb_debug!("xhci_controller: write to crcr {:x}", value);
251         let value = if (self.regs.crcr.get_value() & CRCR_COMMAND_RING_RUNNING) == 0 {
252             self.command_ring_controller
253                 .set_dequeue_pointer(GuestAddress(value & CRCR_COMMAND_RING_POINTER));
254             self.command_ring_controller
255                 .set_consumer_cycle_state((value & CRCR_RING_CYCLE_STATE) > 0);
256             value
257         } else {
258             error!("Write to crcr while command ring is running");
259             self.regs.crcr.get_value()
260         };
261         Ok(value)
262     }
263 
264     // Callback for portsc register write.
portsc_callback(&self, index: u32, value: u32) -> Result<u32>265     fn portsc_callback(&self, index: u32, value: u32) -> Result<u32> {
266         let mut value = value;
267         usb_debug!(
268             "xhci_controller: write to portsc index {} value {:x}",
269             index,
270             value
271         );
272         let port_id = (index + 1) as u8;
273         // xHCI spec 4.19.5. Note: we might want to change this logic if we support USB 3.0.
274         if (value & PORTSC_PORT_RESET) > 0 || (value & PORTSC_WARM_PORT_RESET) > 0 {
275             self.device_slots
276                 .reset_port(port_id)
277                 .map_err(|_| Error::ResetPort)?;
278             value &= !PORTSC_PORT_LINK_STATE_MASK;
279             value &= !PORTSC_PORT_RESET;
280             value |= PORTSC_PORT_ENABLED;
281             value |= PORTSC_PORT_RESET_CHANGE;
282             self.interrupter
283                 .lock()
284                 .send_port_status_change_trb(port_id)
285                 .map_err(Error::SendInterrupt)?;
286         }
287         Ok(value)
288     }
289 
290     // Callback for doorbell register write.
doorbell_callback(&self, index: u32, value: u32) -> Result<()>291     fn doorbell_callback(&self, index: u32, value: u32) -> Result<()> {
292         usb_debug!(
293             "xhci_controller: write to doorbell index {} value {:x}",
294             index,
295             value
296         );
297         let target = (value & DOORBELL_TARGET) as u8;
298         let stream_id: u16 = (value >> DOORBELL_STREAM_ID_OFFSET) as u16;
299         if (self.regs.usbcmd.get_value() & USB_CMD_RUNSTOP) > 0 {
300             // First doorbell is for command ring.
301             if index == 0 {
302                 if target != 0 || stream_id != 0 {
303                     return Ok(());
304                 }
305                 usb_debug!("doorbell to command ring");
306                 self.regs.crcr.set_bits(CRCR_COMMAND_RING_RUNNING);
307                 self.command_ring_controller.start();
308             } else {
309                 usb_debug!("doorbell to device slot");
310                 self.device_slots
311                     .slot(index as u8)
312                     .ok_or(Error::GetDeviceSlot(index as u8))?
313                     .ring_doorbell(target, stream_id)
314                     .map_err(Error::RingDoorbell)?;
315             }
316         }
317         Ok(())
318     }
319 
320     // Callback for iman register write.
iman_callback(&self, value: u32) -> Result<()>321     fn iman_callback(&self, value: u32) -> Result<()> {
322         usb_debug!("xhci_controller: write to iman {:x}", value);
323         let enabled = ((value & IMAN_INTERRUPT_ENABLE) > 0)
324             && ((self.regs.usbcmd.get_value() & USB_CMD_INTERRUPTER_ENABLE) > 0);
325         self.interrupter
326             .lock()
327             .set_enabled(enabled)
328             .map_err(Error::EnableInterrupter)
329     }
330 
331     // Callback for imod register write.
imod_callback(&self, value: u32) -> Result<()>332     fn imod_callback(&self, value: u32) -> Result<()> {
333         usb_debug!("xhci_controller: write to imod {:x}", value);
334         self.interrupter
335             .lock()
336             .set_moderation(
337                 (value & IMOD_INTERRUPT_MODERATION_INTERVAL) as u16,
338                 (value >> IMOD_INTERRUPT_MODERATION_COUNTER_OFFSET) as u16,
339             )
340             .map_err(Error::SetModeration)
341     }
342 
343     // Callback for erstsz register write.
erstsz_callback(&self, value: u32) -> Result<()>344     fn erstsz_callback(&self, value: u32) -> Result<()> {
345         usb_debug!("xhci_controller: write to erstz {:x}", value);
346         self.interrupter
347             .lock()
348             .set_event_ring_seg_table_size((value & ERSTSZ_SEGMENT_TABLE_SIZE) as u16)
349             .map_err(Error::SetupEventRing)
350     }
351 
352     // Callback for erstba register write.
erstba_callback(&self, value: u64) -> Result<()>353     fn erstba_callback(&self, value: u64) -> Result<()> {
354         usb_debug!("xhci_controller: write to erstba {:x}", value);
355         self.interrupter
356             .lock()
357             .set_event_ring_seg_table_base_addr(GuestAddress(
358                 value & ERSTBA_SEGMENT_TABLE_BASE_ADDRESS,
359             ))
360             .map_err(Error::SetupEventRing)
361     }
362 
363     // Callback for erdp register write.
erdp_callback(&self, value: u64) -> Result<()>364     fn erdp_callback(&self, value: u64) -> Result<()> {
365         usb_debug!("xhci_controller: write to erdp {:x}", value);
366         let mut interrupter = self.interrupter.lock();
367         interrupter
368             .set_event_ring_dequeue_pointer(GuestAddress(value & ERDP_EVENT_RING_DEQUEUE_POINTER))
369             .map_err(Error::SetupEventRing)?;
370         interrupter
371             .set_event_handler_busy((value & ERDP_EVENT_HANDLER_BUSY) > 0)
372             .map_err(Error::SetEventHandlerBusy)
373     }
374 
reset(&self) -> Result<()>375     fn reset(&self) -> Result<()> {
376         self.regs.usbsts.set_bits(USB_STS_CONTROLLER_NOT_READY);
377         let usbsts = self.regs.usbsts.clone();
378         self.device_slots.stop_all_and_reset(move || {
379             usbsts.clear_bits(USB_STS_CONTROLLER_NOT_READY);
380         });
381         Ok(())
382     }
383 
halt(&self) -> Result<()>384     fn halt(&self) -> Result<()> {
385         let usbsts = self.regs.usbsts.clone();
386         self.device_slots
387             .stop_all(RingBufferStopCallback::new(move || {
388                 usbsts.set_bits(USB_STS_HALTED);
389             }));
390         Ok(())
391     }
392 }
393