diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2019-01-02 16:31:09 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2019-01-02 16:31:09 -0500 |
commit | c8778707c23a906576c1fdb40dd6ba4090c11773 (patch) | |
tree | 0d9620e663430f054a110cf5244ffc3b9cde33c9 /drivers/pci/controller/dwc | |
parent | 6a790bf0eac449c3b4dd844c2e799037531f6401 (diff) | |
parent | 3f7bb2ec20ce07c02b2002349d256c91a463fcc5 (diff) |
Merge branch 'remotes/lorenzo/pci/dwc-msi'
- Mask DesignWare interrupts instead of disabling them to avoid lost
interrupts (Marc Zyngier)
- Add locking when acking DesignWare interrupts (Marc Zyngier)
- Ack DesignWare interrupts in the proper callbacks (Marc Zyngier)
* remotes/lorenzo/pci/dwc-msi:
PCI: dwc: Move interrupt acking into the proper callback
PCI: dwc: Take lock when ACKing an interrupt
PCI: dwc: Use interrupt masking instead of disabling
Diffstat (limited to 'drivers/pci/controller/dwc')
-rw-r--r-- | drivers/pci/controller/dwc/pcie-designware-host.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/pci/controller/dwc/pcie-designware-host.c b/drivers/pci/controller/dwc/pcie-designware-host.c index 692dd1b264fb..721d60a5d9e4 100644 --- a/drivers/pci/controller/dwc/pcie-designware-host.c +++ b/drivers/pci/controller/dwc/pcie-designware-host.c | |||
@@ -99,9 +99,6 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp) | |||
99 | (i * MAX_MSI_IRQS_PER_CTRL) + | 99 | (i * MAX_MSI_IRQS_PER_CTRL) + |
100 | pos); | 100 | pos); |
101 | generic_handle_irq(irq); | 101 | generic_handle_irq(irq); |
102 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + | ||
103 | (i * MSI_REG_CTRL_BLOCK_SIZE), | ||
104 | 4, 1 << pos); | ||
105 | pos++; | 102 | pos++; |
106 | } | 103 | } |
107 | } | 104 | } |
@@ -168,8 +165,8 @@ static void dw_pci_bottom_mask(struct irq_data *data) | |||
168 | bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; | 165 | bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; |
169 | 166 | ||
170 | pp->irq_status[ctrl] &= ~(1 << bit); | 167 | pp->irq_status[ctrl] &= ~(1 << bit); |
171 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, | 168 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, |
172 | pp->irq_status[ctrl]); | 169 | ~pp->irq_status[ctrl]); |
173 | } | 170 | } |
174 | 171 | ||
175 | raw_spin_unlock_irqrestore(&pp->lock, flags); | 172 | raw_spin_unlock_irqrestore(&pp->lock, flags); |
@@ -191,8 +188,8 @@ static void dw_pci_bottom_unmask(struct irq_data *data) | |||
191 | bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; | 188 | bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL; |
192 | 189 | ||
193 | pp->irq_status[ctrl] |= 1 << bit; | 190 | pp->irq_status[ctrl] |= 1 << bit; |
194 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4, | 191 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4, |
195 | pp->irq_status[ctrl]); | 192 | ~pp->irq_status[ctrl]); |
196 | } | 193 | } |
197 | 194 | ||
198 | raw_spin_unlock_irqrestore(&pp->lock, flags); | 195 | raw_spin_unlock_irqrestore(&pp->lock, flags); |
@@ -200,13 +197,22 @@ static void dw_pci_bottom_unmask(struct irq_data *data) | |||
200 | 197 | ||
201 | static void dw_pci_bottom_ack(struct irq_data *d) | 198 | static void dw_pci_bottom_ack(struct irq_data *d) |
202 | { | 199 | { |
203 | struct msi_desc *msi = irq_data_get_msi_desc(d); | 200 | struct pcie_port *pp = irq_data_get_irq_chip_data(d); |
204 | struct pcie_port *pp; | 201 | unsigned int res, bit, ctrl; |
202 | unsigned long flags; | ||
203 | |||
204 | ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL; | ||
205 | res = ctrl * MSI_REG_CTRL_BLOCK_SIZE; | ||
206 | bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL; | ||
207 | |||
208 | raw_spin_lock_irqsave(&pp->lock, flags); | ||
205 | 209 | ||
206 | pp = msi_desc_to_pci_sysdata(msi); | 210 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, 1 << bit); |
207 | 211 | ||
208 | if (pp->ops->msi_irq_ack) | 212 | if (pp->ops->msi_irq_ack) |
209 | pp->ops->msi_irq_ack(d->hwirq, pp); | 213 | pp->ops->msi_irq_ack(d->hwirq, pp); |
214 | |||
215 | raw_spin_unlock_irqrestore(&pp->lock, flags); | ||
210 | } | 216 | } |
211 | 217 | ||
212 | static struct irq_chip dw_pci_msi_bottom_irq_chip = { | 218 | static struct irq_chip dw_pci_msi_bottom_irq_chip = { |
@@ -658,10 +664,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp) | |||
658 | num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; | 664 | num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL; |
659 | 665 | ||
660 | /* Initialize IRQ Status array */ | 666 | /* Initialize IRQ Status array */ |
661 | for (ctrl = 0; ctrl < num_ctrls; ctrl++) | 667 | for (ctrl = 0; ctrl < num_ctrls; ctrl++) { |
662 | dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE + | 668 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + |
663 | (ctrl * MSI_REG_CTRL_BLOCK_SIZE), | 669 | (ctrl * MSI_REG_CTRL_BLOCK_SIZE), |
664 | 4, &pp->irq_status[ctrl]); | 670 | 4, ~0); |
671 | dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + | ||
672 | (ctrl * MSI_REG_CTRL_BLOCK_SIZE), | ||
673 | 4, ~0); | ||
674 | pp->irq_status[ctrl] = 0; | ||
675 | } | ||
665 | 676 | ||
666 | /* Setup RC BARs */ | 677 | /* Setup RC BARs */ |
667 | dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004); | 678 | dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004); |