mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-05 18:20:34 +00:00
pcie: Implement added GpeNotify() trait
When specific GPE event happens, some devices want to get notification. For example, virtual pcie root port wants to get notification when acpi hotplug GPE occurs. So virtual pcie root port implements this trait. When virtual pcie root port gets this hotplug GPE notification, it will inject a PME into CrOS, CrOS PME handler will wakeup virtual pcie root port and TBT DMA engine, and forbit them to enter into suspend again during hotplug process. Once hotplug process is finished, virtual pcie root port and TBT DMA engine could be allowed to suspend again. BUG=b:185084350 TEST=Verify TBT pcie hotplug function in ManaTEE Change-Id: I6c984e4f81713ad34383f1fb4ea2a5776ac2fccf Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3539565 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
parent
b0d2e4da00
commit
5631839e90
2 changed files with 36 additions and 14 deletions
|
@ -17,6 +17,7 @@ use anyhow::{anyhow, Result};
|
|||
use base::warn;
|
||||
use data_model::DataInit;
|
||||
use resources::{Alloc, SystemAllocator};
|
||||
use vm_control::GpeNotify;
|
||||
|
||||
// reserve 8MB memory window
|
||||
const PCIE_RP_BR_MEM_SIZE: u64 = 0x80_0000;
|
||||
|
@ -255,25 +256,29 @@ impl PcieRootPort {
|
|||
}
|
||||
}
|
||||
|
||||
fn inject_pme(&mut self) {
|
||||
if (self.root_status & PCIE_ROOTSTA_PME_STATUS) != 0 {
|
||||
self.root_status |= PCIE_ROOTSTA_PME_PENDING;
|
||||
self.pme_pending_request_id = self.pci_address;
|
||||
} else {
|
||||
let request_id = self.pci_address.unwrap();
|
||||
let req_id = ((request_id.bus as u32) << 8)
|
||||
| ((request_id.dev as u32) << 3)
|
||||
| (request_id.func as u32);
|
||||
self.root_status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
|
||||
self.root_status |= req_id;
|
||||
self.pme_pending_request_id = None;
|
||||
self.root_status |= PCIE_ROOTSTA_PME_STATUS;
|
||||
self.trigger_pme_interrupt();
|
||||
}
|
||||
}
|
||||
|
||||
// when RP is D3, HP interrupt is disabled by pcie driver, so inject a PME to wakeup
|
||||
// RP first, then inject HP interrupt.
|
||||
fn trigger_hp_or_pme_interrupt(&mut self) {
|
||||
if self.pmc_config.should_trigger_pme() {
|
||||
self.hp_interrupt_pending = true;
|
||||
if (self.root_status & PCIE_ROOTSTA_PME_STATUS) != 0 {
|
||||
self.root_status |= PCIE_ROOTSTA_PME_PENDING;
|
||||
self.pme_pending_request_id = self.pci_address;
|
||||
} else {
|
||||
let request_id = self.pci_address.unwrap();
|
||||
let req_id = ((request_id.bus as u32) << 8)
|
||||
| ((request_id.dev as u32) << 3)
|
||||
| (request_id.func as u32);
|
||||
self.root_status &= !PCIE_ROOTSTA_PME_REQ_ID_MASK;
|
||||
self.root_status |= req_id;
|
||||
self.pme_pending_request_id = None;
|
||||
self.root_status |= PCIE_ROOTSTA_PME_STATUS;
|
||||
self.trigger_pme_interrupt();
|
||||
}
|
||||
self.inject_pme();
|
||||
} else {
|
||||
self.trigger_hp_interrupt();
|
||||
}
|
||||
|
@ -487,3 +492,15 @@ impl HotPlugBus for PcieRootPort {
|
|||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl GpeNotify for PcieRootPort {
|
||||
fn notify(&mut self) {
|
||||
if self.slot_control.is_none() {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.pmc_config.should_trigger_pme() {
|
||||
self.inject_pme();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,6 +107,11 @@ impl Default for VmRunMode {
|
|||
}
|
||||
}
|
||||
|
||||
// Trait for devices that get notification on specific GPE trigger
|
||||
pub trait GpeNotify: Send {
|
||||
fn notify(&mut self) {}
|
||||
}
|
||||
|
||||
pub trait PmResource {
|
||||
fn pwrbtn_evt(&mut self) {}
|
||||
fn gpe_evt(&mut self, _gpe: u32) {}
|
||||
|
|
Loading…
Reference in a new issue