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