X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Fpci%2Fmsi.c;h=07c9f09c856dba943a15f7e794ba8e1eaef78387;hb=cc1bf182bb8451a036a7c227f0a95a0416c4736e;hp=e6740d1a0824d36540b415018814ab6dc3b82344;hpb=a9deecba19b8f384d97f82c75379da48bccb2588;p=linux-2.6 diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index e6740d1a08..07c9f09c85 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c @@ -15,10 +15,10 @@ #include #include #include +#include #include #include -#include #include "pci.h" #include "msi.h" @@ -132,7 +132,7 @@ void read_msi_msg(unsigned int irq, struct msi_msg *msg) pci_read_config_word(dev, msi_data_reg(pos, 1), &data); } else { msg->address_hi = 0; - pci_read_config_word(dev, msi_data_reg(pos, 1), &data); + pci_read_config_word(dev, msi_data_reg(pos, 0), &data); } msg->data = data; break; @@ -224,6 +224,12 @@ static struct msi_desc* alloc_msi_entry(void) return entry; } +static void pci_intx_for_msi(struct pci_dev *dev, int enable) +{ + if (!(dev->dev_flags & PCI_DEV_FLAGS_MSI_INTX_DISABLE_BUG)) + pci_intx(dev, enable); +} + #ifdef CONFIG_PM static void __pci_restore_msi_state(struct pci_dev *dev) { @@ -237,7 +243,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev) entry = get_irq_msi(dev->irq); pos = entry->msi_attrib.pos; - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msi_set_enable(dev, 0); write_msi_msg(dev->irq, &entry->msg); if (entry->msi_attrib.maskbit) @@ -260,7 +266,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev) return; /* route the table */ - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msix_set_enable(dev, 0); list_for_each_entry(entry, &dev->msi_list, list) { @@ -333,7 +339,7 @@ static int msi_capability_init(struct pci_dev *dev) msi_mask_bits_reg(pos, is_64bit_address(control)), maskbits); } - list_add(&entry->list, &dev->msi_list); + list_add_tail(&entry->list, &dev->msi_list); /* Configure MSI capability structure */ ret = arch_setup_msi_irqs(dev, 1, PCI_CAP_ID_MSI); @@ -343,7 +349,7 @@ static int msi_capability_init(struct pci_dev *dev) } /* Set MSI enabled bits */ - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msi_set_enable(dev, 1); dev->msi_enabled = 1; @@ -404,7 +410,7 @@ static int msix_capability_init(struct pci_dev *dev, entry->dev = dev; entry->mask_base = base; - list_add(&entry->list, &dev->msi_list); + list_add_tail(&entry->list, &dev->msi_list); } ret = arch_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSIX); @@ -433,7 +439,7 @@ static int msix_capability_init(struct pci_dev *dev, i++; } /* Set MSI-X enabled bits */ - pci_intx(dev, 0); /* disable intx */ + pci_intx_for_msi(dev, 0); msix_set_enable(dev, 1); dev->msix_enabled = 1; @@ -528,7 +534,7 @@ void pci_disable_msi(struct pci_dev* dev) return; msi_set_enable(dev, 0); - pci_intx(dev, 1); /* enable intx */ + pci_intx_for_msi(dev, 1); dev->msi_enabled = 0; BUG_ON(list_empty(&dev->msi_list)); @@ -549,19 +555,21 @@ static int msi_free_irqs(struct pci_dev* dev) { struct msi_desc *entry, *tmp; - list_for_each_entry(entry, &dev->msi_list, list) - BUG_ON(irq_has_action(entry->irq)); + list_for_each_entry(entry, &dev->msi_list, list) { + if (entry->irq) + BUG_ON(irq_has_action(entry->irq)); + } arch_teardown_msi_irqs(dev); list_for_each_entry_safe(entry, tmp, &dev->msi_list, list) { if (entry->msi_attrib.type == PCI_CAP_ID_MSIX) { - if (list_is_last(&entry->list, &dev->msi_list)) - iounmap(entry->mask_base); - writel(1, entry->mask_base + entry->msi_attrib.entry_nr * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL_OFFSET); + + if (list_is_last(&entry->list, &dev->msi_list)) + iounmap(entry->mask_base); } list_del(&entry->list); kfree(entry); @@ -638,7 +646,7 @@ void pci_disable_msix(struct pci_dev* dev) return; msix_set_enable(dev, 0); - pci_intx(dev, 1); /* enable intx */ + pci_intx_for_msi(dev, 1); dev->msix_enabled = 0; msix_free_all_irqs(dev);