fix(driver/virtio): 修改pci transport中断初始化的位置 (#1018)

* fix(driver/virtio): 修改pci transport中断初始化的位置
This commit is contained in:
黄铭涛 2024-10-29 00:26:16 +08:00 committed by GitHub
parent 55e6f0b65f
commit 84c528f53d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 80 additions and 28 deletions

View File

@ -163,8 +163,14 @@ unsafe impl Sync for VirtIOBlkDevice {}
impl VirtIOBlkDevice {
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
// 设置中断
if let Err(err) = transport.setup_irq(dev_id.clone()) {
error!("VirtIOBlkDevice '{dev_id:?}' setup_irq failed: {:?}", err);
return None;
}
let devname = virtioblk_manager().alloc_id()?;
let irq = transport.irq().map(|irq| IrqNumber::new(irq.data()));
let irq = Some(transport.irq());
let device_inner = VirtIOBlk::<HalImpl, VirtIOTransport>::new(transport);
if let Err(e) = device_inner {
error!("VirtIOBlkDevice '{dev_id:?}' create failed: {:?}", e);

View File

@ -91,6 +91,12 @@ impl Debug for InnerVirtIONetDevice {
impl VirtIONetDevice {
pub fn new(transport: VirtIOTransport, dev_id: Arc<DeviceId>) -> Option<Arc<Self>> {
// 设置中断
if let Err(err) = transport.setup_irq(dev_id.clone()) {
error!("VirtIONetDevice '{dev_id:?}' setup_irq failed: {:?}", err);
return None;
}
let driver_net: VirtIONet<HalImpl, VirtIOTransport, 2> =
match VirtIONet::<HalImpl, VirtIOTransport, 2>::new(transport, 4096) {
Ok(net) => net,

View File

@ -1,8 +1,21 @@
use alloc::{string::ToString, sync::Arc};
use virtio_drivers::transport::Transport;
use crate::exception::HardwareIrqNumber;
use crate::{
driver::{
base::device::DeviceId,
pci::{
pci::{PciDeviceStructure, PciError},
pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqError, PciIrqMsg, IRQ},
},
},
exception::IrqNumber,
};
use super::{transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport};
use super::{
irq::DefaultVirtioIrqHandler, transport_mmio::VirtIOMmioTransport, transport_pci::PciTransport,
};
pub enum VirtIOTransport {
Pci(PciTransport),
@ -10,12 +23,36 @@ pub enum VirtIOTransport {
}
impl VirtIOTransport {
pub fn irq(&self) -> Option<HardwareIrqNumber> {
pub fn irq(&self) -> IrqNumber {
match self {
VirtIOTransport::Mmio(transport) => Some(transport.irq()),
_ => None,
VirtIOTransport::Pci(transport) => transport.irq(),
VirtIOTransport::Mmio(transport) => IrqNumber::new(transport.irq().data()),
}
}
/// 设置中断
pub fn setup_irq(&self, dev_id: Arc<DeviceId>) -> Result<(), PciError> {
if let VirtIOTransport::Pci(transport) = self {
let mut pci_device_guard = transport.pci_device();
let standard_device = pci_device_guard.as_standard_device_mut().unwrap();
standard_device
.irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI)
.ok_or(PciError::PciIrqError(PciIrqError::IrqNotInited))?;
// 中断相关信息
let msg = PciIrqMsg {
irq_common_message: IrqCommonMsg::init_from(
0,
"Virtio_IRQ".to_string(),
&DefaultVirtioIrqHandler,
dev_id,
),
irq_specific_message: IrqSpecificMsg::msi_default(),
};
standard_device.irq_install(msg)?;
standard_device.irq_enable(true)?;
}
return Ok(());
}
}
impl core::fmt::Debug for VirtIOTransport {

View File

@ -6,17 +6,16 @@ use crate::driver::pci::pci::{
PciStandardDeviceBar, PCI_CAP_ID_VNDR,
};
use crate::driver::pci::pci_irq::{IrqCommonMsg, IrqSpecificMsg, PciInterrupt, PciIrqMsg, IRQ};
use crate::driver::pci::root::pci_root_0;
use crate::exception::IrqNumber;
use crate::libs::spinlock::{SpinLock, SpinLockGuard};
use crate::libs::volatile::{
volread, volwrite, ReadOnly, Volatile, VolatileReadable, VolatileWritable, WriteOnly,
};
use crate::mm::VirtAddr;
use alloc::string::ToString;
use alloc::sync::Arc;
use core::{
fmt::{self, Display, Formatter},
@ -28,7 +27,6 @@ use virtio_drivers::{
Error, Hal, PhysAddr,
};
use super::irq::DefaultVirtioIrqHandler;
use super::VIRTIO_VENDOR_ID;
/// The offset to add to a VirtIO device ID to get the corresponding PCI device ID.
@ -104,6 +102,7 @@ pub struct PciTransport {
config_space: Option<NonNull<[u32]>>,
irq: IrqNumber,
dev_id: Arc<DeviceId>,
device: Arc<SpinLock<PciDeviceStructureGeneralDevice>>,
}
impl PciTransport {
@ -140,21 +139,7 @@ impl PciTransport {
// 目前缺少对PCI设备中断号的统一管理所以这里需要指定一个中断号。不能与其他中断重复
let irq_vector = standard_device.irq_vector_mut().unwrap();
irq_vector.push(irq);
standard_device
.irq_init(IRQ::PCI_IRQ_MSIX | IRQ::PCI_IRQ_MSI)
.ok_or(VirtioPciError::UnableToInitIrq)?;
// 中断相关信息
let msg = PciIrqMsg {
irq_common_message: IrqCommonMsg::init_from(
0,
"Virtio_IRQ".to_string(),
&DefaultVirtioIrqHandler,
dev_id.clone(),
),
irq_specific_message: IrqSpecificMsg::msi_default(),
};
standard_device.irq_install(msg)?;
standard_device.irq_enable(true)?;
//device_capability为迭代器遍历其相当于遍历所有的cap空间
for capability in device.capabilities().unwrap() {
if capability.id != PCI_CAP_ID_VNDR {
@ -236,8 +221,17 @@ impl PciTransport {
config_space,
irq,
dev_id,
device: Arc::new(SpinLock::new(device.clone())),
})
}
pub fn pci_device(&self) -> SpinLockGuard<PciDeviceStructureGeneralDevice> {
self.device.lock()
}
pub fn irq(&self) -> IrqNumber {
self.irq
}
}
impl Transport for PciTransport {
@ -446,8 +440,6 @@ pub enum VirtioPciError {
/// `VIRTIO_PCI_CAP_NOTIFY_CFG` capability has a `notify_off_multiplier` that is not a multiple
/// of 2.
InvalidNotifyOffMultiplier(u32),
/// Unable to find capability such as MSIX or MSI.
UnableToInitIrq,
/// No valid `VIRTIO_PCI_CAP_ISR_CFG` capability was found.
MissingIsrConfig,
/// An IO BAR was provided rather than a memory BAR.
@ -477,7 +469,6 @@ impl Display for VirtioPciError {
"PCI device vender ID {:#06x} was not the VirtIO vendor ID {:#06x}.",
vendor_id, VIRTIO_VENDOR_ID
),
Self::UnableToInitIrq => write!(f, "Unable to find capability such as MSIX or MSI."),
Self::MissingCommonConfig => write!(
f,
"No valid `VIRTIO_PCI_CAP_COMMON_CFG` capability was found."

View File

@ -7,7 +7,11 @@ use crate::{
driver::net::{NetDevice, Operstate},
libs::rwlock::RwLockReadGuard,
net::{socket::SocketPollMethod, NET_DEVICES},
time::timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
time::{
sleep::nanosleep,
timer::{next_n_ms_timer_jiffies, Timer, TimerFunction},
PosixTimeSpec,
},
};
use super::{
@ -118,6 +122,14 @@ fn dhcp_query() -> Result<(), SystemError> {
.remove_default_ipv4_route();
}
}
// 在睡眠前释放锁
drop(binding);
let sleep_time = PosixTimeSpec {
tv_sec: 5,
tv_nsec: 0,
};
let _ = nanosleep(sleep_time)?;
}
return Err(SystemError::ETIMEDOUT);