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
This commit is contained in:
commit
c8778707c2
|
@ -99,9 +99,6 @@ irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
|
|||
(i * MAX_MSI_IRQS_PER_CTRL) +
|
||||
pos);
|
||||
generic_handle_irq(irq);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS +
|
||||
(i * MSI_REG_CTRL_BLOCK_SIZE),
|
||||
4, 1 << pos);
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
|
@ -168,8 +165,8 @@ static void dw_pci_bottom_mask(struct irq_data *data)
|
|||
bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
pp->irq_status[ctrl] &= ~(1 << bit);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4,
|
||||
pp->irq_status[ctrl]);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
|
||||
~pp->irq_status[ctrl]);
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
||||
|
@ -191,8 +188,8 @@ static void dw_pci_bottom_unmask(struct irq_data *data)
|
|||
bit = data->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
pp->irq_status[ctrl] |= 1 << bit;
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE + res, 4,
|
||||
pp->irq_status[ctrl]);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK + res, 4,
|
||||
~pp->irq_status[ctrl]);
|
||||
}
|
||||
|
||||
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
||||
|
@ -200,13 +197,22 @@ static void dw_pci_bottom_unmask(struct irq_data *data)
|
|||
|
||||
static void dw_pci_bottom_ack(struct irq_data *d)
|
||||
{
|
||||
struct msi_desc *msi = irq_data_get_msi_desc(d);
|
||||
struct pcie_port *pp;
|
||||
struct pcie_port *pp = irq_data_get_irq_chip_data(d);
|
||||
unsigned int res, bit, ctrl;
|
||||
unsigned long flags;
|
||||
|
||||
pp = msi_desc_to_pci_sysdata(msi);
|
||||
ctrl = d->hwirq / MAX_MSI_IRQS_PER_CTRL;
|
||||
res = ctrl * MSI_REG_CTRL_BLOCK_SIZE;
|
||||
bit = d->hwirq % MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
raw_spin_lock_irqsave(&pp->lock, flags);
|
||||
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + res, 4, 1 << bit);
|
||||
|
||||
if (pp->ops->msi_irq_ack)
|
||||
pp->ops->msi_irq_ack(d->hwirq, pp);
|
||||
|
||||
raw_spin_unlock_irqrestore(&pp->lock, flags);
|
||||
}
|
||||
|
||||
static struct irq_chip dw_pci_msi_bottom_irq_chip = {
|
||||
|
@ -658,10 +664,15 @@ void dw_pcie_setup_rc(struct pcie_port *pp)
|
|||
num_ctrls = pp->num_vectors / MAX_MSI_IRQS_PER_CTRL;
|
||||
|
||||
/* Initialize IRQ Status array */
|
||||
for (ctrl = 0; ctrl < num_ctrls; ctrl++)
|
||||
dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_ENABLE +
|
||||
for (ctrl = 0; ctrl < num_ctrls; ctrl++) {
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_MASK +
|
||||
(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
||||
4, &pp->irq_status[ctrl]);
|
||||
4, ~0);
|
||||
dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_ENABLE +
|
||||
(ctrl * MSI_REG_CTRL_BLOCK_SIZE),
|
||||
4, ~0);
|
||||
pp->irq_status[ctrl] = 0;
|
||||
}
|
||||
|
||||
/* Setup RC BARs */
|
||||
dw_pcie_writel_dbi(pci, PCI_BASE_ADDRESS_0, 0x00000004);
|
||||
|
|
Loading…
Reference in New Issue