2008-11-21 15:57:01 +01:00
|
|
|
# HG changeset patch
|
|
|
|
# User Keir Fraser <keir.fraser@citrix.com>
|
|
|
|
# Date 1226593868 0
|
|
|
|
# Node ID a0910b1b5ec0c938f1c46437df6c28cbeff52c68
|
|
|
|
# Parent d44ad6db638c1308e5ee4a47509769c3cccbe1e8
|
|
|
|
x86: don't disable MSI in order to mask an IRQ
|
|
|
|
|
|
|
|
... as that's not really correct, and there are devices which can't
|
|
|
|
even cope with that. Instead, check whether an MSI IRQ can be masked,
|
|
|
|
and if it can't, treat it just like a level triggered IO-APIC IRQ.
|
|
|
|
|
|
|
|
There's one other bug fix in here, correcting an off-by-one error on
|
|
|
|
the entry_nr range check in __pci_enable_msix().
|
|
|
|
|
|
|
|
Signed-off-by: Jan Beulich <jbeulich@novell.com>
|
|
|
|
|
2009-01-25 01:23:36 +01:00
|
|
|
# HG changeset patch
|
|
|
|
# User Keir Fraser <keir.fraser@citrix.com>
|
|
|
|
# Date 1232549083 0
|
|
|
|
# Node ID af1d9af1a993001bdfdb81d9af1af4fd4a9d3852
|
|
|
|
# Parent 033945166a3a5f3078b1e583bc5e50871ef7e801
|
|
|
|
x86: Fix unmaskable MSI handling.
|
|
|
|
|
|
|
|
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
|
|
|
|
|
|
|
|
--- a/xen/arch/x86/io_apic.c
|
|
|
|
+++ b/xen/arch/x86/io_apic.c
|
|
|
|
@@ -1567,11 +1567,14 @@ static unsigned int startup_msi_vector(u
|
|
|
|
|
|
|
|
static void ack_msi_vector(unsigned int vector)
|
|
|
|
{
|
|
|
|
- ack_APIC_irq();
|
|
|
|
+ if ( msi_maskable_irq(irq_desc[vector].msi_desc) )
|
|
|
|
+ ack_APIC_irq(); /* ACKTYPE_NONE */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void end_msi_vector(unsigned int vector)
|
|
|
|
{
|
|
|
|
+ if ( !msi_maskable_irq(irq_desc[vector].msi_desc) )
|
|
|
|
+ ack_APIC_irq(); /* ACKTYPE_EOI */
|
|
|
|
}
|
|
|
|
|
|
|
|
static void shutdown_msi_vector(unsigned int vector)
|
|
|
|
--- a/xen/arch/x86/irq.c
|
|
|
|
+++ b/xen/arch/x86/irq.c
|
2008-11-21 15:57:01 +01:00
|
|
|
@@ -463,14 +463,19 @@ int pirq_acktype(struct domain *d, int i
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2009-01-25 01:23:36 +01:00
|
|
|
--- a/xen/arch/x86/msi.c
|
|
|
|
+++ b/xen/arch/x86/msi.c
|
2008-11-21 15:57:01 +01:00
|
|
|
@@ -303,6 +303,13 @@ static void msix_flush_writes(unsigned i
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+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;
|
|
|
|
@@ -323,8 +330,6 @@ static void msi_set_mask_bit(unsigned in
|
|
|
|
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:
|
|
|
|
@@ -654,7 +659,7 @@ static int __pci_enable_msix(struct 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;
|
2009-01-25 01:23:36 +01:00
|
|
|
--- a/xen/include/asm-x86/msi.h
|
|
|
|
+++ b/xen/include/asm-x86/msi.h
|
2008-11-21 15:57:01 +01:00
|
|
|
@@ -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,
|