diff options
Diffstat (limited to 'drivers/pci/msi/msi.c')
-rw-r--r-- | drivers/pci/msi/msi.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c index 682fa87747..3a45879d85 100644 --- a/drivers/pci/msi/msi.c +++ b/drivers/pci/msi/msi.c @@ -86,9 +86,11 @@ static int pcim_setup_msi_release(struct pci_dev *dev) return 0; ret = devm_add_action(&dev->dev, pcim_msi_release, dev); - if (!ret) - dev->is_msi_managed = true; - return ret; + if (ret) + return ret; + + dev->is_msi_managed = true; + return 0; } /* @@ -99,9 +101,10 @@ static int pci_setup_msi_context(struct pci_dev *dev) { int ret = msi_setup_device_data(&dev->dev); - if (!ret) - ret = pcim_setup_msi_release(dev); - return ret; + if (ret) + return ret; + + return pcim_setup_msi_release(dev); } /* @@ -349,7 +352,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, struct irq_affinity *affd) { struct irq_affinity_desc *masks = NULL; - struct msi_desc *entry; + struct msi_desc *entry, desc; int ret; /* Reject multi-MSI early on irq domain enabled architectures */ @@ -374,6 +377,12 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, /* All MSIs are unmasked by default; mask them all */ entry = msi_first_desc(&dev->dev, MSI_DESC_ALL); pci_msi_mask(entry, msi_multi_mask(entry)); + /* + * Copy the MSI descriptor for the error path because + * pci_msi_setup_msi_irqs() will free it for the hierarchical + * interrupt domain case. + */ + memcpy(&desc, entry, sizeof(desc)); /* Configure MSI capability structure */ ret = pci_msi_setup_msi_irqs(dev, nvec, PCI_CAP_ID_MSI); @@ -393,7 +402,7 @@ static int msi_capability_init(struct pci_dev *dev, int nvec, goto unlock; err: - pci_msi_unmask(entry, msi_multi_mask(entry)); + pci_msi_unmask(&desc, msi_multi_mask(&desc)); pci_free_msi_irqs(dev); fail: dev->msi_enabled = 0; |