xref: /aosp_15_r20/external/crosvm/devices/src/usb/xhci/intr_resample_handler.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1 // Copyright 2019 The ChromiumOS Authors
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 std::sync::Arc;
6 
7 use anyhow::Context;
8 use base::debug;
9 use base::error;
10 use base::Event;
11 use base::EventType;
12 use sync::Mutex;
13 
14 use super::interrupter::Interrupter;
15 use crate::utils::EventHandler;
16 use crate::utils::EventLoop;
17 
18 /// Interrupt Resample handler handles resample event. It will reassert interrupt if needed.
19 pub struct IntrResampleHandler {
20     interrupter: Arc<Mutex<Interrupter>>,
21     resample_evt: Event,
22 }
23 
24 impl IntrResampleHandler {
25     /// Start resample handler.
start( event_loop: &EventLoop, interrupter: Arc<Mutex<Interrupter>>, resample_evt: Event, ) -> Option<Arc<IntrResampleHandler>>26     pub fn start(
27         event_loop: &EventLoop,
28         interrupter: Arc<Mutex<Interrupter>>,
29         resample_evt: Event,
30     ) -> Option<Arc<IntrResampleHandler>> {
31         let handler = Arc::new(IntrResampleHandler {
32             interrupter,
33             resample_evt,
34         });
35         let tmp_handler: Arc<dyn EventHandler> = handler.clone();
36         if let Err(e) = event_loop.add_event(
37             &handler.resample_evt,
38             EventType::Read,
39             Arc::downgrade(&tmp_handler),
40         ) {
41             error!("cannot add intr resample handler to event loop: {}", e);
42             return None;
43         }
44         Some(handler)
45     }
46 }
47 
48 impl EventHandler for IntrResampleHandler {
on_event(&self) -> anyhow::Result<()>49     fn on_event(&self) -> anyhow::Result<()> {
50         self.resample_evt
51             .wait()
52             .context("cannot read resample evt")?;
53         let mut interrupter = self.interrupter.lock();
54         if !interrupter.event_ring_is_empty() {
55             debug!("irq resample re-assert irq event");
56             // There could be a race condition. When we get resample_evt and other
57             // component is sending interrupt at the same time.
58             // This might result in one more interrupt than we want. It's handled by
59             // kernel correctly.
60             interrupter.interrupt().context("cannot send interrupt")?;
61         }
62         Ok(())
63     }
64 }
65