xref: /aosp_15_r20/external/crosvm/devices/src/sys/linux/acpi.rs (revision bb4ee6a4ae7042d18b07a98463b9c8b875e44b39)
1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2022 The ChromiumOS Authors
2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file.
4*bb4ee6a4SAndroid Build Coastguard Worker 
5*bb4ee6a4SAndroid Build Coastguard Worker use std::sync::Arc;
6*bb4ee6a4SAndroid Build Coastguard Worker 
7*bb4ee6a4SAndroid Build Coastguard Worker use base::debug;
8*bb4ee6a4SAndroid Build Coastguard Worker use base::error;
9*bb4ee6a4SAndroid Build Coastguard Worker use base::info;
10*bb4ee6a4SAndroid Build Coastguard Worker use base::AcpiNotifyEvent;
11*bb4ee6a4SAndroid Build Coastguard Worker use base::NetlinkGenericSocket;
12*bb4ee6a4SAndroid Build Coastguard Worker use sync::Mutex;
13*bb4ee6a4SAndroid Build Coastguard Worker 
14*bb4ee6a4SAndroid Build Coastguard Worker use crate::acpi::ACPIPMError;
15*bb4ee6a4SAndroid Build Coastguard Worker use crate::acpi::GpeResource;
16*bb4ee6a4SAndroid Build Coastguard Worker use crate::acpi::ACPIPM_GPE_MAX;
17*bb4ee6a4SAndroid Build Coastguard Worker use crate::AcAdapter;
18*bb4ee6a4SAndroid Build Coastguard Worker use crate::IrqLevelEvent;
19*bb4ee6a4SAndroid Build Coastguard Worker 
get_acpi_event_sock() -> Result<Option<NetlinkGenericSocket>, ACPIPMError>20*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn get_acpi_event_sock() -> Result<Option<NetlinkGenericSocket>, ACPIPMError> {
21*bb4ee6a4SAndroid Build Coastguard Worker     // Get group id corresponding to acpi_mc_group of acpi_event family
22*bb4ee6a4SAndroid Build Coastguard Worker     let nl_groups: u32;
23*bb4ee6a4SAndroid Build Coastguard Worker     match get_acpi_event_group() {
24*bb4ee6a4SAndroid Build Coastguard Worker         Some(group) if group > 0 => {
25*bb4ee6a4SAndroid Build Coastguard Worker             nl_groups = 1 << (group - 1);
26*bb4ee6a4SAndroid Build Coastguard Worker             info!("Listening on acpi_mc_group of acpi_event family");
27*bb4ee6a4SAndroid Build Coastguard Worker         }
28*bb4ee6a4SAndroid Build Coastguard Worker         _ => {
29*bb4ee6a4SAndroid Build Coastguard Worker             return Err(ACPIPMError::AcpiMcGroupError);
30*bb4ee6a4SAndroid Build Coastguard Worker         }
31*bb4ee6a4SAndroid Build Coastguard Worker     }
32*bb4ee6a4SAndroid Build Coastguard Worker 
33*bb4ee6a4SAndroid Build Coastguard Worker     match NetlinkGenericSocket::new(nl_groups) {
34*bb4ee6a4SAndroid Build Coastguard Worker         Ok(acpi_sock) => Ok(Some(acpi_sock)),
35*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => Err(ACPIPMError::AcpiEventSockError(e)),
36*bb4ee6a4SAndroid Build Coastguard Worker     }
37*bb4ee6a4SAndroid Build Coastguard Worker }
38*bb4ee6a4SAndroid Build Coastguard Worker 
get_acpi_event_group() -> Option<u32>39*bb4ee6a4SAndroid Build Coastguard Worker fn get_acpi_event_group() -> Option<u32> {
40*bb4ee6a4SAndroid Build Coastguard Worker     // Create netlink generic socket which will be used to query about given family name
41*bb4ee6a4SAndroid Build Coastguard Worker     let netlink_ctrl_sock = match NetlinkGenericSocket::new(0) {
42*bb4ee6a4SAndroid Build Coastguard Worker         Ok(sock) => sock,
43*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
44*bb4ee6a4SAndroid Build Coastguard Worker             error!("netlink generic socket creation error: {}", e);
45*bb4ee6a4SAndroid Build Coastguard Worker             return None;
46*bb4ee6a4SAndroid Build Coastguard Worker         }
47*bb4ee6a4SAndroid Build Coastguard Worker     };
48*bb4ee6a4SAndroid Build Coastguard Worker 
49*bb4ee6a4SAndroid Build Coastguard Worker     let nlmsg_family_response = netlink_ctrl_sock
50*bb4ee6a4SAndroid Build Coastguard Worker         .family_name_query("acpi_event".to_string())
51*bb4ee6a4SAndroid Build Coastguard Worker         .unwrap();
52*bb4ee6a4SAndroid Build Coastguard Worker     nlmsg_family_response.get_multicast_group_id("acpi_mc_group".to_string())
53*bb4ee6a4SAndroid Build Coastguard Worker }
54*bb4ee6a4SAndroid Build Coastguard Worker 
acpi_event_run( sci_evt: &IrqLevelEvent, acpi_event_sock: &Option<NetlinkGenericSocket>, gpe0: &Arc<Mutex<GpeResource>>, ignored_gpe: &[u32], ac_adapter: &Option<Arc<Mutex<AcAdapter>>>, )55*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) fn acpi_event_run(
56*bb4ee6a4SAndroid Build Coastguard Worker     sci_evt: &IrqLevelEvent,
57*bb4ee6a4SAndroid Build Coastguard Worker     acpi_event_sock: &Option<NetlinkGenericSocket>,
58*bb4ee6a4SAndroid Build Coastguard Worker     gpe0: &Arc<Mutex<GpeResource>>,
59*bb4ee6a4SAndroid Build Coastguard Worker     ignored_gpe: &[u32],
60*bb4ee6a4SAndroid Build Coastguard Worker     ac_adapter: &Option<Arc<Mutex<AcAdapter>>>,
61*bb4ee6a4SAndroid Build Coastguard Worker ) {
62*bb4ee6a4SAndroid Build Coastguard Worker     let acpi_event_sock = acpi_event_sock.as_ref().unwrap();
63*bb4ee6a4SAndroid Build Coastguard Worker     let nl_msg = match acpi_event_sock.recv() {
64*bb4ee6a4SAndroid Build Coastguard Worker         Ok(msg) => msg,
65*bb4ee6a4SAndroid Build Coastguard Worker         Err(e) => {
66*bb4ee6a4SAndroid Build Coastguard Worker             error!("recv returned with error {}", e);
67*bb4ee6a4SAndroid Build Coastguard Worker             return;
68*bb4ee6a4SAndroid Build Coastguard Worker         }
69*bb4ee6a4SAndroid Build Coastguard Worker     };
70*bb4ee6a4SAndroid Build Coastguard Worker 
71*bb4ee6a4SAndroid Build Coastguard Worker     for netlink_message in nl_msg.iter() {
72*bb4ee6a4SAndroid Build Coastguard Worker         let acpi_event = match AcpiNotifyEvent::new(netlink_message) {
73*bb4ee6a4SAndroid Build Coastguard Worker             Ok(evt) => evt,
74*bb4ee6a4SAndroid Build Coastguard Worker             Err(e) => {
75*bb4ee6a4SAndroid Build Coastguard Worker                 error!("Received netlink message is not an acpi_event, error {}", e);
76*bb4ee6a4SAndroid Build Coastguard Worker                 continue;
77*bb4ee6a4SAndroid Build Coastguard Worker             }
78*bb4ee6a4SAndroid Build Coastguard Worker         };
79*bb4ee6a4SAndroid Build Coastguard Worker         match acpi_event.device_class.as_str() {
80*bb4ee6a4SAndroid Build Coastguard Worker             "gpe" => {
81*bb4ee6a4SAndroid Build Coastguard Worker                 acpi_event_handle_gpe(acpi_event.data, acpi_event._type, gpe0, ignored_gpe);
82*bb4ee6a4SAndroid Build Coastguard Worker             }
83*bb4ee6a4SAndroid Build Coastguard Worker             "ac_adapter" => {
84*bb4ee6a4SAndroid Build Coastguard Worker                 if let Some(ac_adapter) = ac_adapter {
85*bb4ee6a4SAndroid Build Coastguard Worker                     // Currently we only support Status change event - other are ignored
86*bb4ee6a4SAndroid Build Coastguard Worker                     if acpi_event._type == 0x80 {
87*bb4ee6a4SAndroid Build Coastguard Worker                         // Set acex
88*bb4ee6a4SAndroid Build Coastguard Worker                         let ac_gpe_nr = {
89*bb4ee6a4SAndroid Build Coastguard Worker                             let mut ac_adapter = ac_adapter.lock();
90*bb4ee6a4SAndroid Build Coastguard Worker                             ac_adapter.acex = acpi_event.data;
91*bb4ee6a4SAndroid Build Coastguard Worker                             ac_adapter.gpe_nr
92*bb4ee6a4SAndroid Build Coastguard Worker                         };
93*bb4ee6a4SAndroid Build Coastguard Worker 
94*bb4ee6a4SAndroid Build Coastguard Worker                         // Generate GPE
95*bb4ee6a4SAndroid Build Coastguard Worker                         debug!(
96*bb4ee6a4SAndroid Build Coastguard Worker                             "getting ac_adapter event {} type {} and triggering GPE {}",
97*bb4ee6a4SAndroid Build Coastguard Worker                             acpi_event.data, acpi_event._type, ac_gpe_nr
98*bb4ee6a4SAndroid Build Coastguard Worker                         );
99*bb4ee6a4SAndroid Build Coastguard Worker                         let mut gpe0 = gpe0.lock();
100*bb4ee6a4SAndroid Build Coastguard Worker                         match gpe0.set_active(ac_gpe_nr) {
101*bb4ee6a4SAndroid Build Coastguard Worker                             Ok(_) => gpe0.trigger_sci(sci_evt),
102*bb4ee6a4SAndroid Build Coastguard Worker                             Err(e) => error!("{}", e),
103*bb4ee6a4SAndroid Build Coastguard Worker                         }
104*bb4ee6a4SAndroid Build Coastguard Worker                     }
105*bb4ee6a4SAndroid Build Coastguard Worker                 }
106*bb4ee6a4SAndroid Build Coastguard Worker             }
107*bb4ee6a4SAndroid Build Coastguard Worker             c => debug!("ignored acpi event {}", c),
108*bb4ee6a4SAndroid Build Coastguard Worker         };
109*bb4ee6a4SAndroid Build Coastguard Worker     }
110*bb4ee6a4SAndroid Build Coastguard Worker }
111*bb4ee6a4SAndroid Build Coastguard Worker 
acpi_event_handle_gpe( gpe_number: u32, _type: u32, gpe0: &Arc<Mutex<GpeResource>>, ignored_gpe: &[u32], )112*bb4ee6a4SAndroid Build Coastguard Worker fn acpi_event_handle_gpe(
113*bb4ee6a4SAndroid Build Coastguard Worker     gpe_number: u32,
114*bb4ee6a4SAndroid Build Coastguard Worker     _type: u32,
115*bb4ee6a4SAndroid Build Coastguard Worker     gpe0: &Arc<Mutex<GpeResource>>,
116*bb4ee6a4SAndroid Build Coastguard Worker     ignored_gpe: &[u32],
117*bb4ee6a4SAndroid Build Coastguard Worker ) {
118*bb4ee6a4SAndroid Build Coastguard Worker     // If gpe event fired in the host, notify registered GpeNotify listeners
119*bb4ee6a4SAndroid Build Coastguard Worker     if _type == 0 && gpe_number <= ACPIPM_GPE_MAX as u32 && !ignored_gpe.contains(&gpe_number) {
120*bb4ee6a4SAndroid Build Coastguard Worker         if let Some(notify_devs) = gpe0.lock().gpe_notify.get(&gpe_number) {
121*bb4ee6a4SAndroid Build Coastguard Worker             for notify_dev in notify_devs.iter() {
122*bb4ee6a4SAndroid Build Coastguard Worker                 notify_dev.lock().notify();
123*bb4ee6a4SAndroid Build Coastguard Worker             }
124*bb4ee6a4SAndroid Build Coastguard Worker         }
125*bb4ee6a4SAndroid Build Coastguard Worker     }
126*bb4ee6a4SAndroid Build Coastguard Worker }
127