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