diff options
-rw-r--r-- | xen/arch/x86/irq.c | 11 | ||||
-rw-r--r-- | xen/arch/x86/msi.c | 11 | ||||
-rw-r--r-- | xen/include/asm-x86/msi.h | 2 |
3 files changed, 18 insertions, 6 deletions
diff --git a/xen/arch/x86/irq.c b/xen/arch/x86/irq.c index efb73ad011..a4fed17004 100644 --- a/xen/arch/x86/irq.c +++ b/xen/arch/x86/irq.c @@ -463,14 +463,19 @@ int pirq_acktype(struct domain *d, int irq) /* * Edge-triggered IO-APIC and LAPIC interrupts need no final * acknowledgement: we ACK early during interrupt processing. - * MSIs are treated as edge-triggered interrupts. */ if ( !strcmp(desc->handler->typename, "IO-APIC-edge") || - !strcmp(desc->handler->typename, "local-APIC-edge") || - !strcmp(desc->handler->typename, "PCI-MSI") ) + !strcmp(desc->handler->typename, "local-APIC-edge") ) return ACKTYPE_NONE; /* + * MSIs are treated as edge-triggered interrupts, except + * when there is no proper way to mask them. + */ + if ( desc->handler == &pci_msi_type ) + return msi_maskable_irq(desc->msi_desc) ? ACKTYPE_NONE : ACKTYPE_EOI; + + /* * Level-triggered IO-APIC interrupts need to be acknowledged on the CPU * on which they were received. This is because we tickle the LAPIC to EOI. */ diff --git a/xen/arch/x86/msi.c b/xen/arch/x86/msi.c index 8bf5b4a8e3..b5fd6a1f8b 100644 --- a/xen/arch/x86/msi.c +++ b/xen/arch/x86/msi.c @@ -298,6 +298,13 @@ static void msix_flush_writes(unsigned int irq) } } +int msi_maskable_irq(const struct msi_desc *entry) +{ + BUG_ON(!entry); + return entry->msi_attrib.type != PCI_CAP_ID_MSI + || entry->msi_attrib.maskbit; +} + static void msi_set_mask_bit(unsigned int irq, int flag) { struct msi_desc *entry = irq_desc[irq].msi_desc; @@ -318,8 +325,6 @@ static void msi_set_mask_bit(unsigned int irq, int flag) mask_bits &= ~(1); mask_bits |= flag; pci_conf_write32(bus, slot, func, pos, mask_bits); - } else { - msi_set_enable(entry->dev, !flag); } break; case PCI_CAP_ID_MSIX: @@ -649,7 +654,7 @@ static int __pci_enable_msix(struct msi_info *msi) pos = pci_find_cap_offset(msi->bus, slot, func, PCI_CAP_ID_MSIX); control = pci_conf_read16(msi->bus, slot, func, msi_control_reg(pos)); nr_entries = multi_msix_capable(control); - if (msi->entry_nr > nr_entries) + if (msi->entry_nr >= nr_entries) { spin_unlock(&pdev->lock); return -EINVAL; diff --git a/xen/include/asm-x86/msi.h b/xen/include/asm-x86/msi.h index c72f9d69c5..f1462d2dc8 100644 --- a/xen/include/asm-x86/msi.h +++ b/xen/include/asm-x86/msi.h @@ -97,6 +97,8 @@ struct msi_desc { int remap_index; /* index in interrupt remapping table */ }; +int msi_maskable_irq(const struct msi_desc *); + /* * Assume the maximum number of hot plug slots supported by the system is about * ten. The worstcase is that each of these slots is hot-added with a device, |