]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/powerpc/sysdev/fsl_pci.c
Merge branch 'akpm-current/current'
[karo-tx-linux.git] / arch / powerpc / sysdev / fsl_pci.c
index 13b9bcf5485e5f70f340f98c72a51f6e2af4b62b..610f472f91d14c25cef49a118ecc7f1d9eaf73b1 100644 (file)
@@ -179,6 +179,19 @@ static int setup_one_atmu(struct ccsr_pci __iomem *pci,
        return i;
 }
 
+static bool is_kdump(void)
+{
+       struct device_node *node;
+
+       node = of_find_node_by_type(NULL, "memory");
+       if (!node) {
+               WARN_ON_ONCE(1);
+               return false;
+       }
+
+       return of_property_read_bool(node, "linux,usable-memory");
+}
+
 /* atmu setup for fsl pci/pcie controller */
 static void setup_pci_atmu(struct pci_controller *hose)
 {
@@ -192,6 +205,16 @@ static void setup_pci_atmu(struct pci_controller *hose)
        const char *name = hose->dn->full_name;
        const u64 *reg;
        int len;
+       bool setup_inbound;
+
+       /*
+        * If this is kdump, we don't want to trigger a bunch of PCI
+        * errors by closing the window on in-flight DMA.
+        *
+        * We still run most of the function's logic so that things like
+        * hose->dma_window_size still get set.
+        */
+       setup_inbound = !is_kdump();
 
        if (early_find_capability(hose, 0, 0, PCI_CAP_ID_EXP)) {
                if (in_be32(&pci->block_rev1) >= PCIE_IP_REV_2_2) {
@@ -204,8 +227,11 @@ static void setup_pci_atmu(struct pci_controller *hose)
        /* Disable all windows (except powar0 since it's ignored) */
        for(i = 1; i < 5; i++)
                out_be32(&pci->pow[i].powar, 0);
-       for (i = start_idx; i < end_idx; i++)
-               out_be32(&pci->piw[i].piwar, 0);
+
+       if (setup_inbound) {
+               for (i = start_idx; i < end_idx; i++)
+                       out_be32(&pci->piw[i].piwar, 0);
+       }
 
        /* Setup outbound MEM window */
        for(i = 0, j = 1; i < 3; i++) {
@@ -278,6 +304,7 @@ static void setup_pci_atmu(struct pci_controller *hose)
 
        /* Setup inbound mem window */
        mem = memblock_end_of_DRAM();
+       pr_info("%s: end of DRAM %llx\n", __func__, mem);
 
        /*
         * The msi-address-64 property, if it exists, indicates the physical
@@ -320,12 +347,14 @@ static void setup_pci_atmu(struct pci_controller *hose)
 
                piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
 
-               /* Setup inbound memory window */
-               out_be32(&pci->piw[win_idx].pitar,  0x00000000);
-               out_be32(&pci->piw[win_idx].piwbar, 0x00000000);
-               out_be32(&pci->piw[win_idx].piwar,  piwar);
-               win_idx--;
+               if (setup_inbound) {
+                       /* Setup inbound memory window */
+                       out_be32(&pci->piw[win_idx].pitar,  0x00000000);
+                       out_be32(&pci->piw[win_idx].piwbar, 0x00000000);
+                       out_be32(&pci->piw[win_idx].piwar,  piwar);
+               }
 
+               win_idx--;
                hose->dma_window_base_cur = 0x00000000;
                hose->dma_window_size = (resource_size_t)sz;
 
@@ -343,13 +372,15 @@ static void setup_pci_atmu(struct pci_controller *hose)
 
                        piwar = (piwar & ~PIWAR_SZ_MASK) | (mem_log - 1);
 
-                       /* Setup inbound memory window */
-                       out_be32(&pci->piw[win_idx].pitar,  0x00000000);
-                       out_be32(&pci->piw[win_idx].piwbear,
-                                       pci64_dma_offset >> 44);
-                       out_be32(&pci->piw[win_idx].piwbar,
-                                       pci64_dma_offset >> 12);
-                       out_be32(&pci->piw[win_idx].piwar,  piwar);
+                       if (setup_inbound) {
+                               /* Setup inbound memory window */
+                               out_be32(&pci->piw[win_idx].pitar,  0x00000000);
+                               out_be32(&pci->piw[win_idx].piwbear,
+                                               pci64_dma_offset >> 44);
+                               out_be32(&pci->piw[win_idx].piwbar,
+                                               pci64_dma_offset >> 12);
+                               out_be32(&pci->piw[win_idx].piwar,  piwar);
+                       }
 
                        /*
                         * install our own dma_set_mask handler to fixup dma_ops
@@ -362,12 +393,15 @@ static void setup_pci_atmu(struct pci_controller *hose)
        } else {
                u64 paddr = 0;
 
-               /* Setup inbound memory window */
-               out_be32(&pci->piw[win_idx].pitar,  paddr >> 12);
-               out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
-               out_be32(&pci->piw[win_idx].piwar,  (piwar | (mem_log - 1)));
-               win_idx--;
+               if (setup_inbound) {
+                       /* Setup inbound memory window */
+                       out_be32(&pci->piw[win_idx].pitar,  paddr >> 12);
+                       out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
+                       out_be32(&pci->piw[win_idx].piwar,
+                                (piwar | (mem_log - 1)));
+               }
 
+               win_idx--;
                paddr += 1ull << mem_log;
                sz -= 1ull << mem_log;
 
@@ -375,11 +409,15 @@ static void setup_pci_atmu(struct pci_controller *hose)
                        mem_log = ilog2(sz);
                        piwar |= (mem_log - 1);
 
-                       out_be32(&pci->piw[win_idx].pitar,  paddr >> 12);
-                       out_be32(&pci->piw[win_idx].piwbar, paddr >> 12);
-                       out_be32(&pci->piw[win_idx].piwar,  piwar);
-                       win_idx--;
+                       if (setup_inbound) {
+                               out_be32(&pci->piw[win_idx].pitar,
+                                        paddr >> 12);
+                               out_be32(&pci->piw[win_idx].piwbar,
+                                        paddr >> 12);
+                               out_be32(&pci->piw[win_idx].piwar, piwar);
+                       }
 
+                       win_idx--;
                        paddr += 1ull << mem_log;
                }
 
@@ -1002,7 +1040,7 @@ int fsl_pci_mcheck_exception(struct pt_regs *regs)
                        ret = probe_kernel_address((void *)regs->nip, inst);
                }
 
-               if (mcheck_handle_load(regs, inst)) {
+               if (!ret && mcheck_handle_load(regs, inst)) {
                        regs->nip += 4;
                        return 1;
                }