Skip to content

Commit 1577506

Browse files
committed
Merge branch 'pci_interrupts_rework3' into 'master'
Various interrupt handling improvements See merge request redox-os/drivers!282
2 parents cbc4987 + 131063e commit 1577506

File tree

6 files changed

+22
-135
lines changed

6 files changed

+22
-135
lines changed

storage/nvmed/src/main.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -65,18 +65,11 @@ fn get_int_method(
6565
Ok((interrupt_method, interrupt_sources))
6666
} else if has_msi {
6767
// Message signaled interrupts.
68-
let msi_info = match pcid_handle.feature_info(PciFeature::Msi) {
69-
PciFeatureInfo::Msi(msi) => msi,
70-
_ => unreachable!(),
71-
};
7268

7369
let msi_vector_number = 0;
7470
let irq_handle = irq_helpers::allocate_first_msi_interrupt_on_bsp(pcid_handle);
7571

76-
let interrupt_method = InterruptMethod::Msi {
77-
msi_info,
78-
log2_multiple_message_enabled: 0,
79-
};
72+
let interrupt_method = InterruptMethod::Msi;
8073
let interrupt_sources =
8174
InterruptSources::Msi(std::iter::once((msi_vector_number, irq_handle)).collect());
8275

storage/nvmed/src/nvme/mod.rs

Lines changed: 3 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub mod queues;
2121
use self::executor::NvmeExecutor;
2222
pub use self::queues::{NvmeCmd, NvmeCmdQueue, NvmeComp, NvmeCompQueue};
2323

24-
use pcid_interface::msi::{MappedMsixRegs, MsiInfo};
24+
use pcid_interface::msi::MappedMsixRegs;
2525
use pcid_interface::PciFunctionHandle;
2626

2727
/// Used in conjunction with `InterruptMethod`, primarily by the CQ executor.
@@ -31,83 +31,17 @@ pub enum InterruptSources {
3131
Msi(BTreeMap<u8, File>),
3232
Intx(File),
3333
}
34-
impl InterruptSources {
35-
pub fn iter_mut(&mut self) -> impl Iterator<Item = (u16, &mut File)> {
36-
use std::collections::btree_map::IterMut as BTreeIterMut;
37-
use std::iter::Once;
38-
39-
enum IterMut<'a> {
40-
Msi(BTreeIterMut<'a, u8, File>),
41-
MsiX(BTreeIterMut<'a, u16, File>),
42-
Intx(Once<&'a mut File>),
43-
}
44-
impl<'a> Iterator for IterMut<'a> {
45-
type Item = (u16, &'a mut File);
46-
47-
fn next(&mut self) -> Option<Self::Item> {
48-
match self {
49-
&mut Self::Msi(ref mut iter) => iter
50-
.next()
51-
.map(|(&vector, handle)| (u16::from(vector), handle)),
52-
&mut Self::MsiX(ref mut iter) => {
53-
iter.next().map(|(&vector, handle)| (vector, handle))
54-
}
55-
&mut Self::Intx(ref mut iter) => iter.next().map(|handle| (0u16, handle)),
56-
}
57-
}
58-
fn size_hint(&self) -> (usize, Option<usize>) {
59-
match self {
60-
&Self::Msi(ref iter) => iter.size_hint(),
61-
&Self::MsiX(ref iter) => iter.size_hint(),
62-
&Self::Intx(ref iter) => iter.size_hint(),
63-
}
64-
}
65-
}
66-
67-
match self {
68-
&mut Self::MsiX(ref mut map) => IterMut::MsiX(map.iter_mut()),
69-
&mut Self::Msi(ref mut map) => IterMut::Msi(map.iter_mut()),
70-
&mut Self::Intx(ref mut single) => IterMut::Intx(std::iter::once(single)),
71-
}
72-
}
73-
}
7434

7535
/// The way interrupts are sent. Unlike other PCI-based interfaces, like XHCI, it doesn't seem like
7636
/// NVME supports operating with interrupts completely disabled.
7737
pub enum InterruptMethod {
7838
/// Traditional level-triggered, INTx# interrupt pins.
7939
Intx,
8040
/// Message signaled interrupts
81-
Msi {
82-
msi_info: MsiInfo,
83-
log2_multiple_message_enabled: u8,
84-
},
41+
Msi,
8542
/// Extended message signaled interrupts
8643
MsiX(MappedMsixRegs),
8744
}
88-
impl InterruptMethod {
89-
fn is_intx(&self) -> bool {
90-
if let Self::Intx = self {
91-
true
92-
} else {
93-
false
94-
}
95-
}
96-
fn is_msi(&self) -> bool {
97-
if let Self::Msi { .. } = self {
98-
true
99-
} else {
100-
false
101-
}
102-
}
103-
fn is_msix(&self) -> bool {
104-
if let Self::MsiX(_) = self {
105-
true
106-
} else {
107-
false
108-
}
109-
}
110-
}
11145

11246
#[repr(C, packed)]
11347
pub struct NvmeRegs {
@@ -373,18 +307,11 @@ impl Nvme {
373307
self.regs.write().intmc.write(0x0000_0001);
374308
}
375309
}
376-
&mut InterruptMethod::Msi {
377-
msi_info: _,
378-
log2_multiple_message_enabled: log2_enabled_messages,
379-
} => {
310+
&mut InterruptMethod::Msi => {
380311
let mut to_mask = 0x0000_0000;
381312
let mut to_clear = 0x0000_0000;
382313

383314
for (vector, mask) in vectors {
384-
assert!(
385-
vector < (1 << log2_enabled_messages),
386-
"nvmed: internal error: MSI vector out of range"
387-
);
388315
let vector = vector as u8;
389316

390317
if mask {

virtio-core/src/probe.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ pub struct Device {
1818
unsafe impl Send for Device {}
1919
unsafe impl Sync for Device {}
2020

21-
2221
pub const MSIX_PRIMARY_VECTOR: u16 = 0;
2322

2423
/// VirtIO Device Probe

xhcid/src/main.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
extern crate bitflags;
2727

2828
use std::fs::File;
29-
use std::sync::{Arc, Mutex};
29+
use std::sync::Arc;
3030

3131
use pcid_interface::irq_helpers::read_bsp_apic_id;
3232
#[cfg(target_arch = "x86_64")]
@@ -78,10 +78,7 @@ fn get_int_method(pcid_handle: &mut PciFunctionHandle) -> (Option<File>, Interru
7878
table_entry_pointer.write_addr_and_data(msg_addr_and_data);
7979
table_entry_pointer.unmask();
8080

81-
(
82-
Some(interrupt_handle),
83-
InterruptMethod::MsiX(Mutex::new(info)),
84-
)
81+
(Some(interrupt_handle), InterruptMethod::Msi)
8582
};
8683

8784
pcid_handle.enable_feature(PciFeature::MsiX);

xhcid/src/xhci/irq_reactor.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ impl IrqReactor {
121121
fn pause(&self) {
122122
std::thread::sleep(std::time::Duration::from_millis(2));
123123
}
124-
fn run_polling(mut self) {
124+
fn run_polling(mut self) -> ! {
125125
debug!("Running IRQ reactor in polling mode.");
126126
let hci_clone = Arc::clone(&self.hci);
127127

@@ -204,11 +204,11 @@ impl IrqReactor {
204204
run.ints[0].iman.writef(1 << 1, true);
205205
}
206206

207-
fn run_with_irq_file(mut self) {
207+
fn run_with_irq_file(mut self) -> ! {
208208
debug!("Running IRQ reactor with IRQ file and event queue");
209209

210210
let hci_clone = Arc::clone(&self.hci);
211-
let mut event_queue =
211+
let event_queue =
212212
RawEventQueue::new().expect("xhcid irq_reactor: failed to create IRQ event queue");
213213
let irq_fd = self.irq_file.as_ref().unwrap().as_raw_fd();
214214
event_queue
@@ -226,7 +226,8 @@ impl IrqReactor {
226226
};
227227

228228
trace!("IRQ reactor has grabbed the next index in the event ring.");
229-
for _event in event_queue {
229+
'trb_loop: loop {
230+
let _event = event_queue.next_event().unwrap();
230231
trace!("IRQ event queue notified");
231232
let mut buffer = [0u8; 8];
232233

@@ -240,7 +241,7 @@ impl IrqReactor {
240241
if !self.hci.received_irq() {
241242
// continue only when an IRQ to this device was received
242243
trace!("no interrupt pending");
243-
break;
244+
continue 'trb_loop;
244245
}
245246

246247
self.mask_interrupts();
@@ -265,7 +266,7 @@ impl IrqReactor {
265266
}
266267
//hci_clone.event_handler_finished();
267268
self.unmask_interrupts();
268-
return;
269+
continue 'trb_loop;
269270
} else {
270271
count += 1
271272
}
@@ -287,7 +288,7 @@ impl IrqReactor {
287288
debug!("The interrupt bit is no longer pending.");
288289
}
289290
self.unmask_interrupts();
290-
return;
291+
continue 'trb_loop;
291292
}
292293
self.handle_requests();
293294

@@ -309,9 +310,7 @@ impl IrqReactor {
309310

310311
event_trb_index = event_ring.ring.next_index();
311312
}
312-
trace!("Exited event loop!");
313313
}
314-
trace!("IRQ Reactor has finished handling the interrupt");
315314
}
316315

317316
/// Handles device attach/detach events as indicated by a PortStatusChange
@@ -538,7 +537,7 @@ impl IrqReactor {
538537
error!("TODO: grow event ring");
539538
}
540539

541-
pub fn run(mut self) {
540+
pub fn run(self) -> ! {
542541
if self.irq_file.is_some() {
543542
self.run_with_irq_file();
544543
} else {

xhcid/src/xhci/mod.rs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@ use std::collections::BTreeMap;
1313
use std::convert::TryFrom;
1414
use std::fs::File;
1515
use std::sync::atomic::AtomicUsize;
16-
use std::sync::{Arc, Mutex, MutexGuard};
16+
use std::sync::{Arc, Mutex};
1717

1818
use std::{mem, process, slice, thread};
19-
use pcid_interface::msi::MappedMsixRegs;
2019
use syscall::error::{Error, Result, EBADF, EBADMSG, EIO, ENOENT};
2120
use syscall::{EAGAIN, PAGE_SIZE};
2221

@@ -70,11 +69,8 @@ pub enum InterruptMethod {
7069
/// Legacy PCI INTx# interrupt pin.
7170
Intx,
7271

73-
/// Message signaled interrupts.
72+
/// (Extended) Message signaled interrupts.
7473
Msi,
75-
76-
/// Extended message signaled interrupts.
77-
MsiX(Mutex<MappedMsixRegs>),
7874
}
7975

8076
impl Xhci {
@@ -1142,53 +1138,29 @@ impl Xhci {
11421138
Ok(ring)
11431139
}
11441140

1145-
pub fn uses_msi(&self) -> bool {
1146-
if let InterruptMethod::Msi = self.interrupt_method {
1147-
true
1148-
} else {
1149-
false
1150-
}
1151-
}
1152-
pub fn uses_msix(&self) -> bool {
1153-
if let InterruptMethod::MsiX(_) = self.interrupt_method {
1154-
true
1155-
} else {
1156-
false
1157-
}
1158-
}
1159-
// TODO: Perhaps use an rwlock?
1160-
pub fn msix_info(&self) -> Option<MutexGuard<'_, MappedMsixRegs>> {
1161-
match self.interrupt_method {
1162-
InterruptMethod::MsiX(ref info) => Some(info.lock().unwrap()),
1163-
_ => None,
1164-
}
1165-
}
1166-
pub fn msix_info_mut(&self) -> Option<MutexGuard<'_, MappedMsixRegs>> {
1167-
match self.interrupt_method {
1168-
InterruptMethod::MsiX(ref info) => Some(info.lock().unwrap()),
1169-
_ => None,
1170-
}
1141+
fn uses_msi_interrupts(&self) -> bool {
1142+
matches!(self.interrupt_method, InterruptMethod::Msi)
11711143
}
11721144

11731145
/// Checks whether an IRQ has been received from *this* device, in case of an interrupt. Always
11741146
/// true when using MSI/MSI-X.
11751147
pub fn received_irq(&self) -> bool {
11761148
let mut runtime_regs = self.run.lock().unwrap();
11771149

1178-
if self.uses_msi() || self.uses_msix() {
1150+
if self.uses_msi_interrupts() {
11791151
// Since using MSI and MSI-X implies having no IRQ sharing whatsoever, the IP bit
11801152
// doesn't have to be touched.
11811153
trace!(
11821154
"Successfully received MSI/MSI-X interrupt, IP={}, EHB={}",
11831155
runtime_regs.ints[0].iman.readf(1),
1184-
runtime_regs.ints[0].erdp_low.readf(3)
1156+
runtime_regs.ints[0].erdp_low.readf(1 << 3)
11851157
);
11861158
true
11871159
} else if runtime_regs.ints[0].iman.readf(1) {
11881160
trace!(
11891161
"Successfully received INTx# interrupt, IP={}, EHB={}",
11901162
runtime_regs.ints[0].iman.readf(1),
1191-
runtime_regs.ints[0].erdp_low.readf(3)
1163+
runtime_regs.ints[0].erdp_low.readf(1 << 3)
11921164
);
11931165
// If MSI and/or MSI-X are not used, the interrupt might have to be shared, and thus there is
11941166
// a special register to specify whether the IRQ actually came from the xHC.

0 commit comments

Comments
 (0)