93 lines
3.5 KiB
Diff
93 lines
3.5 KiB
Diff
|
# 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>
|
||
|
|
||
|
Index: xen-3.3.1-testing/xen/arch/x86/irq.c
|
||
|
===================================================================
|
||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/irq.c
|
||
|
+++ xen-3.3.1-testing/xen/arch/x86/irq.c
|
||
|
@@ -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.
|
||
|
*/
|
||
|
Index: xen-3.3.1-testing/xen/arch/x86/msi.c
|
||
|
===================================================================
|
||
|
--- xen-3.3.1-testing.orig/xen/arch/x86/msi.c
|
||
|
+++ xen-3.3.1-testing/xen/arch/x86/msi.c
|
||
|
@@ -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;
|
||
|
Index: xen-3.3.1-testing/xen/include/asm-x86/msi.h
|
||
|
===================================================================
|
||
|
--- xen-3.3.1-testing.orig/xen/include/asm-x86/msi.h
|
||
|
+++ xen-3.3.1-testing/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,
|