powerpc/powernv: Fix data type for @r in pnv_ioda_parse_m64_window()
[cascardo/linux.git] / arch / powerpc / platforms / powernv / pci-ioda.c
index 6b95283..d27897a 100644 (file)
@@ -111,17 +111,37 @@ static int __init iommu_setup(char *str)
 }
 early_param("iommu", iommu_setup);
 
-static inline bool pnv_pci_is_mem_pref_64(unsigned long flags)
+static inline bool pnv_pci_is_m64(struct pnv_phb *phb, struct resource *r)
 {
-       return ((flags & (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH)) ==
-               (IORESOURCE_MEM_64 | IORESOURCE_PREFETCH));
+       /*
+        * WARNING: We cannot rely on the resource flags. The Linux PCI
+        * allocation code sometimes decides to put a 64-bit prefetchable
+        * BAR in the 32-bit window, so we have to compare the addresses.
+        *
+        * For simplicity we only test resource start.
+        */
+       return (r->start >= phb->ioda.m64_base &&
+               r->start < (phb->ioda.m64_base + phb->ioda.m64_size));
 }
 
 static struct pnv_ioda_pe *pnv_ioda_init_pe(struct pnv_phb *phb, int pe_no)
 {
+       s64 rc;
+
        phb->ioda.pe_array[pe_no].phb = phb;
        phb->ioda.pe_array[pe_no].pe_number = pe_no;
 
+       /*
+        * Clear the PE frozen state as it might be put into frozen state
+        * in the last PCI remove path. It's not harmful to do so when the
+        * PE is already in unfrozen state.
+        */
+       rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+                                      OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+       if (rc != OPAL_SUCCESS)
+               pr_warn("%s: Error %lld unfreezing PHB#%d-PE#%d\n",
+                       __func__, rc, phb->hose->global_number, pe_no);
+
        return &phb->ioda.pe_array[pe_no];
 }
 
@@ -142,7 +162,7 @@ static void pnv_ioda_reserve_pe(struct pnv_phb *phb, int pe_no)
 
 static struct pnv_ioda_pe *pnv_ioda_alloc_pe(struct pnv_phb *phb)
 {
-       unsigned long pe = phb->ioda.total_pe_num - 1;
+       long pe;
 
        for (pe = phb->ioda.total_pe_num - 1; pe >= 0; pe--) {
                if (!test_and_set_bit(pe, phb->ioda.pe_alloc))
@@ -229,7 +249,7 @@ static void pnv_ioda_reserve_dev_m64_pe(struct pci_dev *pdev,
        sgsz = phb->ioda.m64_segsize;
        for (i = 0; i <= PCI_ROM_RESOURCE; i++) {
                r = &pdev->resource[i];
-               if (!r->parent || !pnv_pci_is_mem_pref_64(r->flags))
+               if (!r->parent || !pnv_pci_is_m64(phb, r))
                        continue;
 
                start = _ALIGN_DOWN(r->start - base, sgsz);
@@ -402,7 +422,7 @@ static void __init pnv_ioda_parse_m64_window(struct pnv_phb *phb)
        struct device_node *dn = hose->dn;
        struct resource *res;
        u32 m64_range[2], i;
-       const u32 *r;
+       const __be32 *r;
        u64 pci_addr;
 
        if (phb->type != PNV_PHB_IODA1 && phb->type != PNV_PHB_IODA2) {
@@ -1877,7 +1897,7 @@ static void pnv_pci_phb3_tce_invalidate(struct pnv_ioda_pe *pe, bool rm,
                                        unsigned shift, unsigned long index,
                                        unsigned long npages)
 {
-       __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, false);
+       __be64 __iomem *invalidate = pnv_ioda_get_inval_reg(pe->phb, rm);
        unsigned long start, end, inc;
 
        /* We'll invalidate DMA address in PE scope */
@@ -2863,7 +2883,7 @@ static void pnv_pci_ioda_fixup_iov_resources(struct pci_dev *pdev)
                res = &pdev->resource[i + PCI_IOV_RESOURCES];
                if (!res->flags || res->parent)
                        continue;
-               if (!pnv_pci_is_mem_pref_64(res->flags)) {
+               if (!pnv_pci_is_m64(phb, res)) {
                        dev_warn(&pdev->dev, "Don't support SR-IOV with"
                                        " non M64 VF BAR%d: %pR. \n",
                                 i, res);
@@ -2958,7 +2978,7 @@ static void pnv_ioda_setup_pe_res(struct pnv_ioda_pe *pe,
                        index++;
                }
        } else if ((res->flags & IORESOURCE_MEM) &&
-                  !pnv_pci_is_mem_pref_64(res->flags)) {
+                  !pnv_pci_is_m64(phb, res)) {
                region.start = res->start -
                               phb->hose->mem_offset[0] -
                               phb->ioda.m32_pci_base;
@@ -3018,6 +3038,38 @@ static void pnv_ioda_setup_pe_seg(struct pnv_ioda_pe *pe)
        }
 }
 
+#ifdef CONFIG_DEBUG_FS
+static int pnv_pci_diag_data_set(void *data, u64 val)
+{
+       struct pci_controller *hose;
+       struct pnv_phb *phb;
+       s64 ret;
+
+       if (val != 1ULL)
+               return -EINVAL;
+
+       hose = (struct pci_controller *)data;
+       if (!hose || !hose->private_data)
+               return -ENODEV;
+
+       phb = hose->private_data;
+
+       /* Retrieve the diag data from firmware */
+       ret = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+                                         PNV_PCI_DIAG_BUF_SIZE);
+       if (ret != OPAL_SUCCESS)
+               return -EIO;
+
+       /* Print the diag data to the kernel log */
+       pnv_pci_dump_phb_diag_data(phb->hose, phb->diag.blob);
+       return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(pnv_pci_diag_data_fops, NULL,
+                       pnv_pci_diag_data_set, "%llu\n");
+
+#endif /* CONFIG_DEBUG_FS */
+
 static void pnv_pci_ioda_create_dbgfs(void)
 {
 #ifdef CONFIG_DEBUG_FS
@@ -3033,9 +3085,14 @@ static void pnv_pci_ioda_create_dbgfs(void)
 
                sprintf(name, "PCI%04x", hose->global_number);
                phb->dbgfs = debugfs_create_dir(name, powerpc_debugfs_root);
-               if (!phb->dbgfs)
+               if (!phb->dbgfs) {
                        pr_warning("%s: Error on creating debugfs on PHB#%x\n",
                                __func__, hose->global_number);
+                       continue;
+               }
+
+               debugfs_create_file("dump_diag_regs", 0200, phb->dbgfs, hose,
+                                   &pnv_pci_diag_data_fops);
        }
 #endif /* CONFIG_DEBUG_FS */
 }
@@ -3083,9 +3140,12 @@ static resource_size_t pnv_pci_window_alignment(struct pci_bus *bus,
                bridge = bridge->bus->self;
        }
 
-       /* We fail back to M32 if M64 isn't supported */
-       if (phb->ioda.m64_segsize &&
-           pnv_pci_is_mem_pref_64(type))
+       /*
+        * We fall back to M32 if M64 isn't supported. We enforce the M64
+        * alignment for any 64-bit resource, PCIe doesn't care and
+        * bridges only do 64-bit prefetchable anyway.
+        */
+       if (phb->ioda.m64_segsize && (type & IORESOURCE_MEM_64))
                return phb->ioda.m64_segsize;
        if (type & IORESOURCE_MEM)
                return phb->ioda.m32_segsize;
@@ -3125,7 +3185,7 @@ static void pnv_pci_fixup_bridge_resources(struct pci_bus *bus,
                w = NULL;
                if (r->flags & type & IORESOURCE_IO)
                        w = &hose->io_resource;
-               else if (pnv_pci_is_mem_pref_64(r->flags) &&
+               else if (pnv_pci_is_m64(phb, r) &&
                         (type & IORESOURCE_PREFETCH) &&
                         phb->ioda.m64_segsize)
                        w = &hose->mem_resources[1];
@@ -3722,10 +3782,11 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
        if (rc)
                pr_warning("  OPAL Error %ld performing IODA table reset !\n", rc);
 
-       /* If we're running in kdump kerenl, the previous kerenl never
+       /*
+        * If we're running in kdump kernel, the previous kernel never
         * shutdown PCI devices correctly. We already got IODA table
         * cleaned out. So we have to issue PHB reset to stop all PCI
-        * transactions from previous kerenl.
+        * transactions from previous kernel.
         */
        if (is_kdump_kernel()) {
                pr_info("  Issue PHB reset ...\n");