]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
PCI: iproc: Invalidate PAXB address mapping before programming it
authorAbhishek Shah <abhishek.shah@broadcom.com>
Fri, 6 Sep 2019 03:58:13 +0000 (09:28 +0530)
committerLorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Fri, 25 Oct 2019 09:18:00 +0000 (10:18 +0100)
Invalidate PAXB inbound/outbound address mapping on probe before
programming it.

Kernel relies on outbound/inbound windows VALID bit in OARR registers to
detect if a window was programmed and if it is set it does not overwrite
it.

This causes issues on soft reboot (eg kexec) since the host controller
does not go through a HW reset on softboot so the kernel detects valid
outbound/inbound windows configuration and is not able to reprogramme
it as expected.

Therefore, in order to make sure outbound/inbound windows are
reprogrammed on soft reboot (eg kexec), invalidate memory windows on
each probe to fix the issue.

Signed-off-by: Abhishek Shah <abhishek.shah@broadcom.com>
Signed-off-by: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
Reviewed-by: Ray Jui <ray.jui@broadcom.com>
Reviewed-by: Andrew Murray <andrew.murray@arm.com>
drivers/pci/controller/pcie-iproc.c

index 2d457bfdaf66e624c5a537a940efdbe87719d5e3..9a5c352259448af87dde434b102f729e2b4fbad8 100644 (file)
@@ -1245,6 +1245,32 @@ static int iproc_pcie_map_dma_ranges(struct iproc_pcie *pcie)
        return ret;
 }
 
+static void iproc_pcie_invalidate_mapping(struct iproc_pcie *pcie)
+{
+       struct iproc_pcie_ib *ib = &pcie->ib;
+       struct iproc_pcie_ob *ob = &pcie->ob;
+       int idx;
+
+       if (pcie->ep_is_internal)
+               return;
+
+       if (pcie->need_ob_cfg) {
+               /* iterate through all OARR mapping regions */
+               for (idx = ob->nr_windows - 1; idx >= 0; idx--) {
+                       iproc_pcie_write_reg(pcie,
+                                            MAP_REG(IPROC_PCIE_OARR0, idx), 0);
+               }
+       }
+
+       if (pcie->need_ib_cfg) {
+               /* iterate through all IARR mapping regions */
+               for (idx = 0; idx < ib->nr_regions; idx++) {
+                       iproc_pcie_write_reg(pcie,
+                                            MAP_REG(IPROC_PCIE_IARR0, idx), 0);
+               }
+       }
+}
+
 static int iproce_pcie_get_msi(struct iproc_pcie *pcie,
                               struct device_node *msi_node,
                               u64 *msi_addr)
@@ -1517,6 +1543,8 @@ int iproc_pcie_setup(struct iproc_pcie *pcie, struct list_head *res)
        iproc_pcie_perst_ctrl(pcie, true);
        iproc_pcie_perst_ctrl(pcie, false);
 
+       iproc_pcie_invalidate_mapping(pcie);
+
        if (pcie->need_ob_cfg) {
                ret = iproc_pcie_map_ranges(pcie, res);
                if (ret) {