> Well… Yes. BUT to be clear: Having MSI does *not* mean that the driver does not need some
method to determine if the device has interrupted.
Sure - after all, interrupt may be just spurious. For example, it may be raised as a write to the local APIC’s ICR
by some “bold experimenter”…
The driver might check an in-memory structure, for example.
…which is of zero use if this “bold experimenter” happens to be Alberto - IIRC, he was about to raise MSI interrupts as a write by the CPU to the memory that is supposed to be written to only by MSI-capable device (you remember this nonsense that he was about to do, don’t you)…
If the MSI vector WERE to be shared (it’s possible, I believe, just not supported in Windows)
all the attached ISRs would be called in any case (per my description of edge-triggered interrupts, above).
Well, it does not necessarily have to work this way. For example, consider the following approach in interrupt handler stub for shared MSI interrupts (I assume interrupts have been already re-enabled on the CPU)
cli();
spinlock(irq->lock);
ack__interrupt();
if( irq->flags & FLAG_ISR_ALREADY_RUNS)
{
irq->flags |= FLAG_ISR_REPLAY;
can_proceed =0;
}
else
{
irq->flags |= FLAG_ISR_ALREADY_RUNS;
can_proceed =1;
}
while(1)
{
spin_unlock(irq->lock);
sti();
if(! can_proceed) break;
invoke_shared_msi_isr_chain(irq);
cli();
spinlock(irq->lock);
if( irq->flags & FLAG_ISR_REPLAY)
{
irq->flags &= ~FLAG_ISR_REPLAY;
can_proceed =1;
}
else
{
irq->flags = 0;
can_proceed =0;
}
}
As you can see, we are not going to lose interrupts even if invoke_shared_msi_isr_chain() returns immediately after the one of ISRs in a chain returns TRUE. In order to make it consistent with the existing model of interrupt spinlocks invoke_shared_msi_isr_chain() will have to acquire a separate spinlock for each interrupt source and hold it while the corresponding ISR runs…
Anton Bassov