From 97a77c2884712f76321cb550a9615f8a84c251cf Mon Sep 17 00:00:00 2001 From: Ruihan Li Date: Wed, 14 Jan 2026 21:19:52 +0800 Subject: [PATCH] Lazily acquire MSI-X resources --- Cargo.lock | 1 + kernel/comps/pci/Cargo.toml | 1 + kernel/comps/pci/src/capability/mod.rs | 201 ++++++++++-------- kernel/comps/pci/src/capability/msix.rs | 135 ++++++------ kernel/comps/pci/src/capability/vendor.rs | 28 ++- kernel/comps/pci/src/common_device.rs | 62 +++--- .../comps/virtio/src/transport/pci/device.rs | 55 ++--- .../comps/virtio/src/transport/pci/driver.rs | 6 +- .../comps/virtio/src/transport/pci/legacy.rs | 15 +- 9 files changed, 266 insertions(+), 238 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 513726330..c417b5540 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -279,6 +279,7 @@ dependencies = [ "cfg-if", "component", "fdt", + "int-to-c-enum", "log", "ostd", "spin", diff --git a/kernel/comps/pci/Cargo.toml b/kernel/comps/pci/Cargo.toml index 92e973c23..b21468dac 100644 --- a/kernel/comps/pci/Cargo.toml +++ b/kernel/comps/pci/Cargo.toml @@ -10,6 +10,7 @@ align_ext.workspace = true bitflags.workspace = true cfg-if.workspace = true component.workspace = true +int-to-c-enum.workspace = true log.workspace = true ostd.workspace = true spin.workspace = true diff --git a/kernel/comps/pci/src/capability/mod.rs b/kernel/comps/pci/src/capability/mod.rs index ac224a86d..b6e5ee53b 100644 --- a/kernel/comps/pci/src/capability/mod.rs +++ b/kernel/comps/pci/src/capability/mod.rs @@ -5,80 +5,83 @@ use alloc::vec::Vec; use align_ext::AlignExt; +use int_to_c_enum::TryFromInt; +use ostd::Result; -use self::{msix::CapabilityMsixData, vendor::CapabilityVndrData}; -use super::{cfg_space::Status, common_device::PciCommonDevice}; -use crate::cfg_space::PciGeneralDeviceCfgOffset; +use self::{ + msix::{CapabilityMsixData, RawCapabilityMsix}, + vendor::{CapabilityVndrData, RawCapabilityVndr}, +}; +use crate::{ + PciDeviceLocation, + cfg_space::{PciGeneralDeviceCfgOffset, Status}, + common_device::{BarManager, PciCommonDevice}, +}; pub mod msix; pub mod vendor; -/// PCI Capability -#[derive(Debug)] -pub struct Capability { - cap_data: CapabilityData, +/// Raw PCI Capabilities. +#[derive(Debug, Default)] +pub(super) struct RawCapabilities { + msix: Option, + vndr: Vec, } -/// PCI Capability data. -#[derive(Debug, Clone)] -pub enum CapabilityData { - /// Id:0x01, Power Management - Pm, - /// Id:0x02, Accelerated Graphics Part - Agp, - /// Id:0x03, Vital Product Data - Vpd, - /// Id:0x04, Slot Identification - SlotId, - /// Id:0x05, Message Signalled Interrupts - Msi, - /// Id:0x06, CompactPCI HotSwap - Chswp, - /// Id:0x07, PCI-X - PciX, - /// Id:0x08, HyperTransport - Hp, - /// Id:0x09, Vendor-Specific - Vndr(CapabilityVndrData), - /// Id:0x0A, Debug port - Dbg, - /// Id:0x0B, CompactPCI Central Resource Control - Ccrc, - /// Id:0x0C, PCI Standard Hot-Plug Controller - Shpc, - /// Id:0x0D, Bridge subsystem vendor/device ID - Ssvid, - /// Id:0x0R, AGP Target PCI-PCI bridge - Agp3, - /// Id:0x0F, Secure Device - Secdev, - /// Id:0x10, PCI Express - Exp, - /// Id:0x11, MSI-X - Msix(CapabilityMsixData), - /// Id:0x12, SATA Data/Index Conf - Sata, - /// Id:0x13, PCI Advanced Features - Af, - /// Id:0x14, Enhanced Allocation - Ea, - /// Id:?, Unknown - Unknown(u8), +/// PCI capability types. +#[derive(Debug, Clone, Copy, TryFromInt)] +#[repr(u8)] +enum CapabilityType { + /// Power Management + Pm = 0x01, + /// Accelerated Graphics Part + Agp = 0x02, + /// Vital Product Data + Vpd = 0x03, + /// Slot Identification + SlotId = 0x04, + /// Message Signalled Interrupts + Msi = 0x05, + /// CompactPCI HotSwap + Chswp = 0x06, + /// PCI-X + PciX = 0x07, + /// HyperTransport + Hp = 0x08, + /// Vendor-Specific + Vndr = 0x09, + /// Debug port + Dbg = 0x0A, + /// CompactPCI Central Resource Control + Ccrc = 0x0B, + /// PCI Standard Hot-Plug Controller + Shpc = 0x0C, + /// Bridge subsystem vendor/device ID + Ssvid = 0x0D, + /// AGP Target PCI-PCI bridge + Agp3 = 0x0E, + /// Secure Device + Secdev = 0x0F, + /// PCI Express + Exp = 0x10, + /// MSI-X + Msix = 0x11, + /// SATA Data/Index Conf + Sata = 0x12, + /// PCI Advanced Features + Af = 0x13, + /// Enhanced Allocation + Ea = 0x14, } -impl Capability { +impl RawCapabilities { /// The top of the capability position. const CAPABILITY_TOP: u16 = 0xFC; - /// Gets the capability data - pub fn capability_data(&self) -> &CapabilityData { - &self.cap_data - } - - /// Gets the capabilities of one device - pub(super) fn device_capabilities(dev: &mut PciCommonDevice) -> Vec { + /// Parses the capabilities of the PCI device. + pub(super) fn parse(dev: &PciCommonDevice) -> Self { if !dev.read_status().contains(Status::CAPABILITIES_LIST) { - return Vec::new(); + return Self::default(); } // The offset of the first capability pointer is the same for PCI general devices and PCI @@ -87,7 +90,6 @@ impl Capability { let mut cap_ptr = (dev.location().read8(CAP_OFFSET) as u16).align_down(align_of::() as _); let mut cap_ptr_vec = Vec::new(); - let mut capabilities = Vec::new(); // Read all capability pointers so that it is easy for us to get the length of each // capability. @@ -100,39 +102,60 @@ impl Capability { // Push the top position so that we can calculate the length of the last capability. cap_ptr_vec.push(Self::CAPABILITY_TOP); + let mut caps = Self::default(); + let length = cap_ptr_vec.len(); for i in 0..length - 1 { let cap_ptr = cap_ptr_vec[i]; let next_ptr = cap_ptr_vec[i + 1]; - let cap_type = dev.location().read8(cap_ptr); - let data = match cap_type { - 0x01 => CapabilityData::Pm, - 0x02 => CapabilityData::Agp, - 0x03 => CapabilityData::Vpd, - 0x04 => CapabilityData::SlotId, - 0x05 => CapabilityData::Msi, - 0x06 => CapabilityData::Chswp, - 0x07 => CapabilityData::PciX, - 0x08 => CapabilityData::Hp, - 0x09 => { - CapabilityData::Vndr(CapabilityVndrData::new(dev, cap_ptr, next_ptr - cap_ptr)) - } - 0x0A => CapabilityData::Dbg, - 0x0B => CapabilityData::Ccrc, - 0x0C => CapabilityData::Shpc, - 0x0D => CapabilityData::Ssvid, - 0x0E => CapabilityData::Agp3, - 0x0F => CapabilityData::Secdev, - 0x10 => CapabilityData::Exp, - 0x11 => CapabilityData::Msix(CapabilityMsixData::new(dev, cap_ptr)), - 0x12 => CapabilityData::Sata, - 0x13 => CapabilityData::Af, - 0x14 => CapabilityData::Ea, - _ => CapabilityData::Unknown(cap_type), + let raw_cap_type = dev.location().read8(cap_ptr); + + let Ok(cap_type) = CapabilityType::try_from(raw_cap_type) else { + continue; }; - capabilities.push(Self { cap_data: data }); + match cap_type { + CapabilityType::Msix => { + // "More than one MSI-X Capability structure per Function is prohibited." + if caps.msix.is_some() { + log::warn!( + "superfluous MSI-X Capability structures at {:?} are ignored", + dev.location() + ); + continue; + } + caps.msix = Some(RawCapabilityMsix::parse(dev, cap_ptr)); + } + CapabilityType::Vndr => { + caps.vndr + .push(RawCapabilityVndr::new(cap_ptr, next_ptr - cap_ptr)); + } + _ => {} + } } - capabilities + caps + } + + /// Acquires a new [`CapabilityMsixData`] instance. + pub(super) fn acquire_msix_data( + &self, + loc: &PciDeviceLocation, + bar_manager: &mut BarManager, + ) -> Result> { + let Some(raw_msix) = self.msix.as_ref() else { + return Ok(None); + }; + + Ok(Some(CapabilityMsixData::new(loc, bar_manager, raw_msix)?)) + } + + /// Iterates over [`CapabilityVndrData`] instances. + pub(super) fn iter_vndr_data( + &self, + loc: &PciDeviceLocation, + ) -> impl Iterator { + self.vndr + .iter() + .map(|raw_vndr| CapabilityVndrData::new(loc, raw_vndr)) } } diff --git a/kernel/comps/pci/src/capability/msix.rs b/kernel/comps/pci/src/capability/msix.rs index 71cee6dd5..d1057446d 100644 --- a/kernel/comps/pci/src/capability/msix.rs +++ b/kernel/comps/pci/src/capability/msix.rs @@ -4,16 +4,42 @@ use alloc::vec::Vec; -use ostd::{io::IoMem, irq::IrqLine, mm::VmIoOnce}; +use ostd::{Error, Result, io::IoMem, irq::IrqLine, mm::VmIoOnce}; use crate::{ PciDeviceLocation, arch::{MSIX_DEFAULT_MSG_ADDR, construct_remappable_msix_address}, - cfg_space::{BarAccess, Command}, - common_device::PciCommonDevice, + cfg_space::{BarAccess, Command, PciCommonCfgOffset}, + common_device::{BarManager, PciCommonDevice}, }; -/// MSI-X capability. It will set the BAR space it uses to be hidden. +/// Raw information about MSI-X capability. +#[derive(Debug)] +pub(super) struct RawCapabilityMsix { + cap_ptr: u16, + msg_ctrl: u16, + table_info: u32, + pba_info: u32, +} + +impl RawCapabilityMsix { + pub(super) fn parse(dev: &PciCommonDevice, cap_ptr: u16) -> Self { + let msg_ctrl = dev.location().read16(cap_ptr + 2); + let table_info = dev.location().read32(cap_ptr + 4); + let pba_info = dev.location().read32(cap_ptr + 8); + + Self { + cap_ptr, + msg_ctrl, + table_info, + pba_info, + } + } +} + +/// MSI-X capability. +/// +/// It will acquire the access to the BAR space it uses. #[derive(Debug)] pub struct CapabilityMsixData { loc: PciDeviceLocation, @@ -23,69 +49,41 @@ pub struct CapabilityMsixData { /// | Vector Control: u32 | Msg Data: u32 | Msg Upper Addr: u32 | Msg Addr: u32 | table_bar: IoMem, /// Pending bits table. + #[expect(dead_code)] pending_table_bar: IoMem, table_offset: usize, + #[expect(dead_code)] pending_table_offset: usize, irqs: Vec>, } -impl Clone for CapabilityMsixData { - fn clone(&self) -> Self { - let new_vec = self.irqs.clone().to_vec(); - Self { - loc: self.loc, - ptr: self.ptr, - table_size: self.table_size, - table_bar: self.table_bar.clone(), - pending_table_bar: self.pending_table_bar.clone(), - irqs: new_vec, - table_offset: self.table_offset, - pending_table_offset: self.pending_table_offset, - } - } -} - impl CapabilityMsixData { - pub(super) fn new(dev: &mut PciCommonDevice, cap_ptr: u16) -> Self { - // Get Table and PBA offset, provide functions to modify them - let table_info = dev.location().read32(cap_ptr + 4); - let pba_info = dev.location().read32(cap_ptr + 8); - - let table_bar; - let pba_bar; - - let bar_manager = dev.bar_manager_mut(); - match bar_manager - .bar_mut((pba_info & 0b111) as u8) - .expect("MSIX cfg:pba BAR is none") - .acquire() - .expect("MSIX cfg:pba BAR is unavailable") + pub(super) fn new( + loc: &PciDeviceLocation, + bar_manager: &mut BarManager, + raw_cap: &RawCapabilityMsix, + ) -> Result { + let pba_bar = match bar_manager + .bar_mut((raw_cap.pba_info & 0b111) as u8) + .ok_or(Error::InvalidArgs)? + .acquire()? { - BarAccess::Memory(io_mem) => { - pba_bar = io_mem.clone(); - } - BarAccess::Io => { - panic!("MSIX cfg:pba BAR is IO type") - } + BarAccess::Memory(io_mem) => io_mem, + BarAccess::Io => return Err(Error::InvalidArgs), }; - match bar_manager - .bar_mut((table_info & 0b111) as u8) - .expect("MSIX cfg:table BAR is none") - .acquire() - .expect("MSIX cfg:table BAR is unavailable") + let pba_offset = (raw_cap.pba_info & !(0b111u32)) as usize; + + let table_bar = match bar_manager + .bar_mut((raw_cap.table_info & 0b111) as u8) + .ok_or(Error::InvalidArgs)? + .acquire()? { - BarAccess::Memory(io_mem) => { - table_bar = io_mem.clone(); - } - BarAccess::Io => { - panic!("MSIX cfg:table BAR is IO type") - } - } + BarAccess::Memory(io_mem) => io_mem, + BarAccess::Io => return Err(Error::InvalidArgs), + }; + let table_offset = (raw_cap.table_info & !(0b111u32)) as usize; - let pba_offset = (pba_info & !(0b111u32)) as usize; - let table_offset = (table_info & !(0b111u32)) as usize; - - let table_size = (dev.location().read16(cap_ptr + 2) & 0b11_1111_1111) + 1; + let table_size = (raw_cap.msg_ctrl & 0b11_1111_1111) + 1; // Set the message address and disable all MSI-X vectors. let message_address = MSIX_DEFAULT_MSG_ADDR; @@ -103,32 +101,37 @@ impl CapabilityMsixData { } // Enable MSI-X (bit 15: MSI-X Enable). - dev.location() - .write16(cap_ptr + 2, dev.location().read16(cap_ptr + 2) | 0x8000); + loc.write16( + raw_cap.cap_ptr + 2, + loc.read16(raw_cap.cap_ptr + 2) | 0x8000, + ); // Disable INTx. Enable bus master. - dev.write_command(dev.read_command() | Command::INTERRUPT_DISABLE | Command::BUS_MASTER); + loc.write16( + PciCommonCfgOffset::Command as u16, + loc.read16(PciCommonCfgOffset::Command as u16) + | (Command::INTERRUPT_DISABLE | Command::BUS_MASTER).bits(), + ); let mut irqs = Vec::with_capacity(table_size as usize); for _ in 0..table_size { irqs.push(None); } - Self { - loc: *dev.location(), - ptr: cap_ptr, - table_size: (dev.location().read16(cap_ptr + 2) & 0b11_1111_1111) + 1, + Ok(Self { + loc: *loc, + ptr: raw_cap.cap_ptr, + table_size, table_bar, pending_table_bar: pba_bar, irqs, table_offset, pending_table_offset: pba_offset, - } + }) } /// Returns the size of the MSI-X Table. pub fn table_size(&self) -> u16 { - // bit 10:0 table size - (self.loc.read16(self.ptr + 2) & 0b11_1111_1111) + 1 + self.table_size } /// Enables an interrupt line. diff --git a/kernel/comps/pci/src/capability/vendor.rs b/kernel/comps/pci/src/capability/vendor.rs index adcd6868a..4670081fa 100644 --- a/kernel/comps/pci/src/capability/vendor.rs +++ b/kernel/comps/pci/src/capability/vendor.rs @@ -4,10 +4,24 @@ use ostd::{Error, Result}; -use crate::{PciDeviceLocation, common_device::PciCommonDevice}; +use crate::PciDeviceLocation; -/// Vendor specific capability. Users can access this capability area at will, -/// except for the PCI configuration space which cannot be accessed at will through this structure. +/// Raw information about vendor-specific capability. +#[derive(Debug)] +pub(super) struct RawCapabilityVndr { + cap_ptr: u16, + length: u16, +} + +impl RawCapabilityVndr { + pub(super) fn new(cap_ptr: u16, length: u16) -> Self { + Self { cap_ptr, length } + } +} + +/// Vendor-specific capability. +/// +/// Users can access this capability area at will. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct CapabilityVndrData { location: PciDeviceLocation, @@ -16,11 +30,11 @@ pub struct CapabilityVndrData { } impl CapabilityVndrData { - pub(super) fn new(dev: &PciCommonDevice, cap_ptr: u16, length: u16) -> Self { + pub(super) fn new(loc: &PciDeviceLocation, raw_cap: &RawCapabilityVndr) -> Self { Self { - location: *dev.location(), - cap_ptr, - length, + location: *loc, + cap_ptr: raw_cap.cap_ptr, + length: raw_cap.length, } } diff --git a/kernel/comps/pci/src/common_device.rs b/kernel/comps/pci/src/common_device.rs index e5cb33275..355745bbc 100644 --- a/kernel/comps/pci/src/common_device.rs +++ b/kernel/comps/pci/src/common_device.rs @@ -2,16 +2,12 @@ //! PCI device common definitions or functions. -use alloc::vec::Vec; +use ostd::Result; -use super::{ - capability::Capability, - cfg_space::{AddrLen, Bar, Command, Status}, - device_info::PciDeviceId, -}; use crate::{ - cfg_space::{PciBridgeCfgOffset, PciCommonCfgOffset}, - device_info::PciDeviceLocation, + capability::{RawCapabilities, msix::CapabilityMsixData, vendor::CapabilityVndrData}, + cfg_space::{AddrLen, Bar, Command, PciBridgeCfgOffset, PciCommonCfgOffset, Status}, + device_info::{PciDeviceId, PciDeviceLocation}, }; /// PCI common device. @@ -23,7 +19,7 @@ pub struct PciCommonDevice { location: PciDeviceLocation, header_type: PciHeaderType, bar_manager: BarManager, - capabilities: Vec, + capabilities: RawCapabilities, } impl PciCommonDevice { @@ -47,16 +43,6 @@ impl PciCommonDevice { &mut self.bar_manager } - /// Returns the PCI capabilities. - pub fn capabilities(&self) -> &Vec { - &self.capabilities - } - - /// Returns the PCI capabilities and a mutable reference to the BAR manager. - pub fn capabilities_and_bar_manager_mut(&mut self) -> (&Vec, &mut BarManager) { - (&self.capabilities, &mut self.bar_manager) - } - /// Returns the PCI device type. pub fn device_type(&self) -> PciDeviceType { self.header_type.device_type() @@ -83,20 +69,41 @@ impl PciCommonDevice { Status::from_bits_truncate(self.location.read16(PciCommonCfgOffset::Status as u16)) } + /// Acquires necessary resources to build the MSI-X capability data, if the capability exists. + /// + /// Note that the MSI-X capability data occupies some memory BARs. Therefore, it will fail if + /// the necessary resources are not available. + pub fn acquire_msix_capability(&mut self) -> Result> { + self.capabilities + .acquire_msix_data(&self.location, &mut self.bar_manager) + } + + /// Gets access to the vendor-specific capability data. + pub fn iter_vndr_capability(&self) -> impl Iterator { + self.capabilities.iter_vndr_data(&self.location) + } + + /// Gets access to the vendor-specific capability data with a mutable reference to the BAR + /// manager. + pub fn iter_vndr_capability_with_bar_manager( + &mut self, + ) -> (impl Iterator, &mut BarManager) { + ( + self.capabilities.iter_vndr_data(&self.location), + &mut self.bar_manager, + ) + } + pub(super) fn new(location: PciDeviceLocation) -> Option { if location.read16(0) == 0xFFFF { // No device. return None; } - let capabilities = Vec::new(); let device_id = PciDeviceId::new(location); - let bar_manager = BarManager { - bars: [const { None }; 6], - }; + let mut header_type = PciHeaderType::try_from_raw(location.read8(PciCommonCfgOffset::HeaderType as u16))?; - if let PciDeviceType::PciToPciBridge(primary_bus, secondary_bus, subordinate_bus) = &mut header_type.device_type { @@ -105,6 +112,11 @@ impl PciCommonDevice { *subordinate_bus = location.read8(PciBridgeCfgOffset::SubordinateBusNumber as u16); } + let bar_manager = BarManager { + bars: [const { None }; 6], + }; + let capabilities = RawCapabilities::default(); + let mut device = Self { device_id, location, @@ -121,7 +133,7 @@ impl PciCommonDevice { device.bar_manager = BarManager::new(device.header_type.device_type(), location); device.write_command(command_val | (Command::MEMORY_SPACE | Command::IO_SPACE)); - device.capabilities = Capability::device_capabilities(&mut device); + device.capabilities = RawCapabilities::parse(&device); Some(device) } diff --git a/kernel/comps/virtio/src/transport/pci/device.rs b/kernel/comps/virtio/src/transport/pci/device.rs index 9a304f6cc..9e7ac6264 100644 --- a/kernel/comps/virtio/src/transport/pci/device.rs +++ b/kernel/comps/virtio/src/transport/pci/device.rs @@ -4,8 +4,7 @@ use alloc::{boxed::Box, sync::Arc}; use core::fmt::Debug; use aster_pci::{ - PciDeviceId, bus::PciDevice, capability::CapabilityData, cfg_space::BarAccess, - common_device::PciCommonDevice, + PciDeviceId, bus::PciDevice, cfg_space::BarAccess, common_device::PciCommonDevice, }; use aster_util::{field_ptr, safe_ptr::SafePtr}; use log::{info, warn}; @@ -284,50 +283,38 @@ impl VirtioPciModernTransport { info!("[Virtio]: Found device:{:?}", device_type); - let mut msix = None; let mut notify = None; let mut common_cfg = None; let mut device_cfg = None; - let (caps, bar_manager) = common_device.capabilities_and_bar_manager_mut(); - for cap in caps { - match cap.capability_data() { - CapabilityData::Vndr(vendor) => { - let data = VirtioPciCapabilityData::new(bar_manager, *vendor); - match data.typ() { - VirtioPciCpabilityType::CommonCfg => { - common_cfg = Some(VirtioPciCommonCfg::new(&data)); - } - VirtioPciCpabilityType::NotifyCfg => { - notify = Some(VirtioPciNotify { - offset_multiplier: data.option_value().unwrap(), - offset: data.offset(), - io_memory: data.memory_bar().unwrap().clone(), - }); - } - VirtioPciCpabilityType::IsrCfg => {} - VirtioPciCpabilityType::DeviceCfg => { - device_cfg = Some(data); - } - VirtioPciCpabilityType::PciCfg => {} - } + let (vndr_caps, bar_manager) = common_device.iter_vndr_capability_with_bar_manager(); + for vndr_cap in vndr_caps { + let data = VirtioPciCapabilityData::new(bar_manager, vndr_cap); + match data.typ() { + VirtioPciCpabilityType::CommonCfg => { + common_cfg = Some(VirtioPciCommonCfg::new(&data)); } - CapabilityData::Msix(data) => { - msix = Some(data.clone()); + VirtioPciCpabilityType::NotifyCfg => { + notify = Some(VirtioPciNotify { + offset_multiplier: data.option_value().unwrap(), + offset: data.offset(), + io_memory: data.memory_bar().unwrap().clone(), + }); } - CapabilityData::Unknown(id) => { - panic!("unknown capability: {}", id) - } - _ => { - panic!("PCI Virtio device should not have other type of capability") + VirtioPciCpabilityType::IsrCfg => {} + VirtioPciCpabilityType::DeviceCfg => { + device_cfg = Some(data); } + VirtioPciCpabilityType::PciCfg => {} } } - // TODO: Support interrupt without MSI-X - let msix = msix.unwrap(); let notify = notify.unwrap(); let common_cfg = common_cfg.unwrap(); let device_cfg = device_cfg.unwrap(); + + // TODO: Support interrupt without MSI-X. + let msix = common_device.acquire_msix_capability().unwrap().unwrap(); let msix_manager = VirtioMsixManager::new(msix); + Ok(Self { common_device, common_cfg, diff --git a/kernel/comps/virtio/src/transport/pci/driver.rs b/kernel/comps/virtio/src/transport/pci/driver.rs index d58264c0f..eb6744053 100644 --- a/kernel/comps/virtio/src/transport/pci/driver.rs +++ b/kernel/comps/virtio/src/transport/pci/driver.rs @@ -4,7 +4,6 @@ use alloc::{boxed::Box, collections::vec_deque::VecDeque, sync::Arc}; use aster_pci::{ bus::{PciDevice, PciDriver}, - capability::CapabilityData, common_device::PciCommonDevice, }; use ostd::{bus::BusProbeError, sync::SpinLock}; @@ -42,10 +41,7 @@ impl PciDriver for VirtioPciDriver { return Err((BusProbeError::DeviceNotMatch, device)); } - let has_vendor_cap = device - .capabilities() - .iter() - .any(|cap| matches!(cap.capability_data(), CapabilityData::Vndr(_))); + let has_vendor_cap = device.iter_vndr_capability().next().is_some(); let device_id = *device.device_id(); let transport: Box = match device_id.device_id { 0x1000..0x1040 if (device.device_id().revision_id == 0) => { diff --git a/kernel/comps/virtio/src/transport/pci/legacy.rs b/kernel/comps/virtio/src/transport/pci/legacy.rs index ad7088bcb..bdb2c6d5d 100644 --- a/kernel/comps/virtio/src/transport/pci/legacy.rs +++ b/kernel/comps/virtio/src/transport/pci/legacy.rs @@ -3,7 +3,7 @@ use alloc::{boxed::Box, sync::Arc}; use core::fmt::Debug; -use aster_pci::{capability::CapabilityData, cfg_space::BarAccess, common_device::PciCommonDevice}; +use aster_pci::{cfg_space::BarAccess, common_device::PciCommonDevice}; use aster_util::safe_ptr::SafePtr; use log::{info, warn}; use ostd::{ @@ -112,17 +112,8 @@ impl VirtioPciLegacyTransport { num_queues += 1; } - // TODO: Support interrupt without MSI-X - let mut msix = None; - for cap in common_device.capabilities().iter() { - match cap.capability_data() { - CapabilityData::Msix(data) => { - msix = Some(data.clone()); - } - _ => continue, - } - } - let Some(msix) = msix else { + // TODO: Support interrupt without MSI-X. + let Ok(Some(msix)) = common_device.acquire_msix_capability() else { return Err((BusProbeError::ConfigurationSpaceError, common_device)); }; let msix_manager = VirtioMsixManager::new(msix);