Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/sys/linux/acpi.rs
5394 views
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
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
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
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
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
128