Mitch Williams <[EMAIL PROTECTED]> writes: > This patch fixes a kernel bug which is triggered when using the > irqbalance daemon with MSI-X hardware. > > Because both MSI-X interrupt messages and MSI-X table writes are posted, > it's possible for them to cross while in-flight. This results in > interrupts being received long after the kernel thinks they're disabled, > and in interrupts being sent to stale vectors after rebalancing. > > This patch performs a read flush after writes to the MSI-X table for > mask and unmask operations. Since the SMP affinity is set while > the interrupt is masked, and since it's unmasked immediately after, > no additional flushes are required in the various affinity setting > routines. > > This patch has been validated with (unreleased) network hardware which > uses MSI-X. > > Revised with input from Eric Biederman.
Acked-by: "Eric W. Biederman" <[EMAIL PROTECTED]> > > Signed-off-by: Mitch Williams <[EMAIL PROTECTED]> > > diff -urpN -X dontdiff linux-2.6.21-rc5-clean/drivers/pci/msi.c > linux-2.6.21-rc5/drivers/pci/msi.c > --- linux-2.6.21-rc5-clean/drivers/pci/msi.c 2007-03-28 10:05:24.000000000 > -0700 > +++ linux-2.6.21-rc5/drivers/pci/msi.c 2007-03-28 09:21:34.000000000 > -0700 > @@ -68,6 +68,29 @@ static void msix_set_enable(struct pci_d > } > } > > +static void msix_flush_writes(unsigned int irq) > +{ > + struct msi_desc *entry; > + > + entry = get_irq_msi(irq); > + BUG_ON(!entry || !entry->dev); > + switch (entry->msi_attrib.type) { > + case PCI_CAP_ID_MSI: > + /* nothing to do */ > + break; > + case PCI_CAP_ID_MSIX: > + { > + int offset = entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + > + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET; > + readl(entry->mask_base + offset); > + break; > + } > + default: > + BUG(); > + break; > + } > +} > + > static void msi_set_mask_bit(unsigned int irq, int flag) > { > struct msi_desc *entry; > @@ -186,11 +209,13 @@ void write_msi_msg(unsigned int irq, str > void mask_msi_irq(unsigned int irq) > { > msi_set_mask_bit(irq, 1); > + msix_flush_writes(irq); > } > > void unmask_msi_irq(unsigned int irq) > { > msi_set_mask_bit(irq, 0); > + msix_flush_writes(irq); > } > > static int msi_free_irq(struct pci_dev* dev, int irq); - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/