PCI: cadence: Use AXI region 0 to signal interrupts from EP
authorAlan Douglas <adouglas@cadence.com>
Thu, 11 Oct 2018 16:15:43 +0000 (17:15 +0100)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Fri, 12 Oct 2018 11:09:04 +0000 (12:09 +0100)
The IRQ physical address is allocated from region 0, rather than
the highest region. Update the driver to reserve this region in
the bitmap and to use region 0 for all types of interrupt.

This corrects a problem which prevents the interrupt being
signalled correctly if using the first address in the AXI region,
since an offset of zero will always be mapped to region 0.

Fixes: 37dddf14f1ae ("PCI: cadence: Add EndPoint Controller driver for Cadence PCIe controller")
Signed-off-by: Alan Douglas <adouglas@cadence.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
drivers/pci/controller/pcie-cadence-ep.c

index 9e87dd7..6692654 100644 (file)
@@ -258,7 +258,6 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn,
                                     u8 intx, bool is_asserted)
 {
        struct cdns_pcie *pcie = &ep->pcie;
-       u32 r = ep->max_regions - 1;
        u32 offset;
        u16 status;
        u8 msg_code;
@@ -268,8 +267,8 @@ static void cdns_pcie_ep_assert_intx(struct cdns_pcie_ep *ep, u8 fn,
        /* Set the outbound region if needed. */
        if (unlikely(ep->irq_pci_addr != CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY ||
                     ep->irq_pci_fn != fn)) {
-               /* Last region was reserved for IRQ writes. */
-               cdns_pcie_set_outbound_region_for_normal_msg(pcie, fn, r,
+               /* First region was reserved for IRQ writes. */
+               cdns_pcie_set_outbound_region_for_normal_msg(pcie, fn, 0,
                                                             ep->irq_phys_addr);
                ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_LEGACY;
                ep->irq_pci_fn = fn;
@@ -347,8 +346,8 @@ static int cdns_pcie_ep_send_msi_irq(struct cdns_pcie_ep *ep, u8 fn,
        /* Set the outbound region if needed. */
        if (unlikely(ep->irq_pci_addr != (pci_addr & ~pci_addr_mask) ||
                     ep->irq_pci_fn != fn)) {
-               /* Last region was reserved for IRQ writes. */
-               cdns_pcie_set_outbound_region(pcie, fn, ep->max_regions - 1,
+               /* First region was reserved for IRQ writes. */
+               cdns_pcie_set_outbound_region(pcie, fn, 0,
                                              false,
                                              ep->irq_phys_addr,
                                              pci_addr & ~pci_addr_mask,
@@ -517,6 +516,8 @@ static int cdns_pcie_ep_probe(struct platform_device *pdev)
                goto free_epc_mem;
        }
        ep->irq_pci_addr = CDNS_PCIE_EP_IRQ_PCI_ADDR_NONE;
+       /* Reserve region 0 for IRQs */
+       set_bit(0, &ep->ob_region_map);
 
        return 0;