diff options
| author | Tony Truong <truong@codeaurora.org> | 2017-03-29 12:16:51 -0700 |
|---|---|---|
| committer | Tony Truong <truong@codeaurora.org> | 2017-04-04 12:53:35 -0700 |
| commit | f83b25b95d2cd9fb6329ba4a95b94a2fbbde3c91 (patch) | |
| tree | 03132bfb1bb2bd430046c35bba017290410ccc70 /drivers/pci/host | |
| parent | 4c332132fc72dd634004f76d92534995feaad15c (diff) | |
msm: pcie: update teardown sequence for PCIe MSI interrupt
Update the teardown sequence for PCIe MSI to support
multiple endpoints.
Change-Id: I1fbdb840bf3677e30d4d27a50503c5cc70ece272
Signed-off-by: Tony Truong <truong@codeaurora.org>
Diffstat (limited to 'drivers/pci/host')
| -rw-r--r-- | drivers/pci/host/pci-msm.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c index eade4f85632a..01abb1adec30 100644 --- a/drivers/pci/host/pci-msm.c +++ b/drivers/pci/host/pci-msm.c @@ -5573,34 +5573,54 @@ static irqreturn_t handle_global_irq(int irq, void *data) return IRQ_HANDLED; } -void msm_pcie_destroy_irq(unsigned int irq, struct msm_pcie_dev_t *pcie_dev) +void msm_pcie_destroy_irq(unsigned int irq) { - int pos, i; + int pos; + struct pci_dev *pdev = irq_get_chip_data(irq); + struct msi_desc *entry = irq_get_msi_desc(irq); + struct msi_desc *firstentry; struct msm_pcie_dev_t *dev; + u32 nvec; + int firstirq; - if (pcie_dev) - dev = pcie_dev; - else - dev = irq_get_chip_data(irq); + if (!pdev) { + pr_err("PCIe: pci device is null. IRQ:%d\n", irq); + return; + } + dev = PCIE_BUS_PRIV_DATA(pdev->bus); if (!dev) { - pr_err("PCIe: device is null. IRQ:%d\n", irq); + pr_err("PCIe: could not find RC. IRQ:%d\n", irq); + return; + } + + if (!entry) { + PCIE_ERR(dev, "PCIe: RC%d: msi desc is null. IRQ:%d\n", + dev->rc_idx, irq); return; } + firstentry = first_pci_msi_entry(pdev); + if (!firstentry) { + PCIE_ERR(dev, + "PCIe: RC%d: firstentry msi desc is null. IRQ:%d\n", + dev->rc_idx, irq); + return; + } + + firstirq = firstentry->irq; + nvec = (1 << entry->msi_attrib.multiple); + if (dev->msi_gicm_addr) { PCIE_DBG(dev, "destroy QGIC based irq %d\n", irq); - for (i = 0; i < MSM_PCIE_MAX_MSI; i++) - if (irq == dev->msi[i].num) - break; - if (i == MSM_PCIE_MAX_MSI) { + if (irq < firstirq || irq > firstirq + nvec - 1) { PCIE_ERR(dev, "Could not find irq: %d in RC%d MSI table\n", irq, dev->rc_idx); return; } else { - pos = i; + pos = irq - firstirq; } } else { PCIE_DBG(dev, "destroy default MSI irq %d\n", irq); @@ -5620,7 +5640,7 @@ void msm_pcie_destroy_irq(unsigned int irq, struct msm_pcie_dev_t *pcie_dev) void arch_teardown_msi_irq(unsigned int irq) { PCIE_GEN_DBG("irq %d deallocated\n", irq); - msm_pcie_destroy_irq(irq, NULL); + msm_pcie_destroy_irq(irq); } void arch_teardown_msi_irqs(struct pci_dev *dev) @@ -5639,7 +5659,7 @@ void arch_teardown_msi_irqs(struct pci_dev *dev) continue; nvec = 1 << entry->msi_attrib.multiple; for (i = 0; i < nvec; i++) - msm_pcie_destroy_irq(entry->irq + i, pcie_dev); + arch_teardown_msi_irq(entry->irq + i); } } @@ -5701,6 +5721,7 @@ static int arch_setup_msi_irq_default(struct pci_dev *pdev, PCIE_DBG(dev, "irq %d allocated\n", irq); + irq_set_chip_data(irq, pdev); irq_set_msi_desc(irq, desc); /* write msi vector and data */ @@ -5768,6 +5789,7 @@ static int arch_setup_msi_irq_qgic(struct pci_dev *pdev, firstirq = irq; irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING); + irq_set_chip_data(irq, pdev); } /* write msi vector and data */ @@ -5845,7 +5867,6 @@ static int msm_pcie_msi_map(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq) { irq_set_chip_and_handler (irq, &pcie_msi_chip, handle_simple_irq); - irq_set_chip_data(irq, domain->host_data); return 0; } |
