mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
pci: Add support for reserving but not allocating slots
This can be used in a two pass approach where all configs that can hold PCI devices are evaluated to reserve any specific PCI device IDs they may need. Those device IDs will later be allocated when the devices are added to the bus. The tri-state Free, Reserved, Allocated also catches the problem of hotplugging a device with a specific, already used, device ID. Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -498,7 +498,7 @@ pub enum DeviceManagerError {
|
||||
|
||||
/// Could not reserve the PCI device ID.
|
||||
#[error("Could not reserve the PCI device ID")]
|
||||
GetPciDeviceId(#[source] pci::PciRootError),
|
||||
ReservePciDeviceId(#[source] pci::PciRootError),
|
||||
|
||||
/// Could not give the PCI device ID back.
|
||||
#[error("Could not give the PCI device ID back")]
|
||||
@@ -4550,8 +4550,8 @@ impl DeviceManager {
|
||||
.pci_bus
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_device_id(pci_device_bdf.device() as usize)
|
||||
.map_err(DeviceManagerError::GetPciDeviceId)?;
|
||||
.allocate_device_id(Some(pci_device_bdf.device()))
|
||||
.map_err(DeviceManagerError::AllocatePciDeviceId)?;
|
||||
|
||||
(pci_segment_id, pci_device_bdf, resources)
|
||||
} else {
|
||||
|
||||
+15
-4
@@ -164,6 +164,17 @@ impl PciSegment {
|
||||
)
|
||||
}
|
||||
|
||||
/// Reserves a device ID on this PCI segment, marking it as in-use
|
||||
/// so that automatic allocation will not use it.
|
||||
pub(crate) fn reserve_device_id(&self, device_id: u8) -> DeviceManagerResult<()> {
|
||||
self.pci_bus
|
||||
.lock()
|
||||
.unwrap()
|
||||
.reserve_device_id(device_id)
|
||||
.map_err(DeviceManagerError::ReservePciDeviceId)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Allocates a device's ID on this PCI segment.
|
||||
///
|
||||
/// - `device_id`: Device ID to request for allocation
|
||||
@@ -613,17 +624,17 @@ mod unit_tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
// Test to acquire a device ID that is invalid, one that is already taken
|
||||
// and one being greater than the number of allowed devices per bus.
|
||||
// Test that reserving an already taken device ID fails and that
|
||||
// allocating an out-of-range device ID fails.
|
||||
fn allocate_device_id_invalid_device_id() {
|
||||
// The first address is occupied by the root
|
||||
let already_taken_device_id = 0x0_u8;
|
||||
let overflow_device_id = 0xff_u8;
|
||||
let segment = setup();
|
||||
let bdf_res = segment.allocate_device_id(Some(already_taken_device_id));
|
||||
let bdf_res = segment.reserve_device_id(already_taken_device_id);
|
||||
assert!(matches!(
|
||||
bdf_res,
|
||||
Err(DeviceManagerError::GetPciDeviceId(e)) if matches!(
|
||||
Err(DeviceManagerError::ReservePciDeviceId(e)) if matches!(
|
||||
e,
|
||||
pci::PciRootError::AlreadyInUsePciDeviceSlot(0x0)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user