If the PCI-CFG access on the specific PHB, to return 0xFF's for
reading and drop writing. The patch implements that for PowerNV
platform. The patch also removes the check on "hose == NULL"
for PCI-CFG accessors since the kernel should stop while fetching
platform-dependent PHB (struct pnv_phb).

Signed-off-by: Gavin Shan <sha...@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/eeh-powernv.c |   10 ++---
 arch/powerpc/platforms/powernv/pci.c         |   59 ++++++++++++++++++++------
 arch/powerpc/platforms/powernv/pci.h         |    4 ++
 3 files changed, 54 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c 
b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 20a7865..249798e 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -328,9 +328,9 @@ static int powernv_eeh_read_config(struct device_node *dn, 
int where,
 {
        struct eeh_dev *edev = of_node_to_eeh_dev(dn);
        struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
-       struct pci_controller *hose = edev->phb;
 
-       return hose->ops->read(dev->bus, dev->devfn, where, size, val);
+       return pnv_pci_cfg_read(dev->bus, dev->devfn,
+                               where, size, val, false);
 }
 
 /**
@@ -347,11 +347,9 @@ static int powernv_eeh_write_config(struct device_node 
*dn, int where,
 {
        struct eeh_dev *edev = of_node_to_eeh_dev(dn);
        struct pci_dev *dev = eeh_dev_to_pci_dev(edev);
-       struct pci_controller *hose = edev->phb;
 
-       hose = pci_bus_to_host(dev->bus);
-
-       return hose->ops->write(dev->bus, dev->devfn, where, size, val);
+       return pnv_pci_cfg_write(dev->bus, dev->devfn,
+                                where, size, val, false);
 }
 
 /**
diff --git a/arch/powerpc/platforms/powernv/pci.c 
b/arch/powerpc/platforms/powernv/pci.c
index 1f31826..47fa921 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -255,21 +255,30 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, 
struct pci_bus *bus,
                pnv_pci_handle_eeh_config(phb, pe_no);
 }
 
-static int pnv_pci_read_config(struct pci_bus *bus,
-                              unsigned int devfn,
-                              int where, int size, u32 *val)
+int pnv_pci_cfg_read(struct pci_bus *bus,
+                    unsigned int devfn,
+                    int where, int size,
+                    u32 *val, bool check)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct pnv_phb *phb = hose->private_data;
+       u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
+       s64 rc;
 #ifdef CONFIG_EEH
        struct device_node *busdn, *dn;
        struct eeh_pe *phb_pe = NULL;
-#endif
-       u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
-       s64 rc;
 
-       if (hose == NULL)
+       /*
+        * If PCI-CFG access has been blocked, we simply
+        * return 0xFF's here.
+        */
+       if (check &&
+           (phb->eeh_state & PNV_EEH_STATE_ENABLED) &&
+           (phb->eeh_state & PNV_EEH_STATE_CFG_BLOCKED)) {
+               *val = 0xFFFFFFFF;
                return PCIBIOS_DEVICE_NOT_FOUND;
+       }
+#endif
 
        switch (size) {
        case 1: {
@@ -329,19 +338,26 @@ static int pnv_pci_read_config(struct pci_bus *bus,
        return PCIBIOS_SUCCESSFUL;
 }
 
-static int pnv_pci_write_config(struct pci_bus *bus,
-                               unsigned int devfn,
-                               int where, int size, u32 val)
+int pnv_pci_cfg_write(struct pci_bus *bus,
+                     unsigned int devfn,
+                     int where, int size,
+                     u32 val, bool check)
 {
        struct pci_controller *hose = pci_bus_to_host(bus);
        struct pnv_phb *phb = hose->private_data;
        u32 bdfn = (((uint64_t)bus->number) << 8) | devfn;
 
-       if (hose == NULL)
-               return PCIBIOS_DEVICE_NOT_FOUND;
-
        cfg_dbg("pnv_pci_write_config bus: %x devfn: %x +%x/%x -> %08x\n",
                bus->number, devfn, where, size, val);
+
+#ifdef CONFIG_EEH
+       /* If PCI-CFG access has been blocked, drop it */
+       if (check &&
+           (phb->eeh_state & PNV_EEH_STATE_ENABLED) &&
+           (phb->eeh_state & PNV_EEH_STATE_CFG_BLOCKED))
+               return PCIBIOS_DEVICE_NOT_FOUND;
+#endif
+
        switch (size) {
        case 1:
                opal_pci_config_write_byte(phb->opal_id, bdfn, where, val);
@@ -367,6 +383,23 @@ static int pnv_pci_write_config(struct pci_bus *bus,
        return PCIBIOS_SUCCESSFUL;
 }
 
+static int pnv_pci_read_config(struct pci_bus *bus,
+                              unsigned int devfn,
+                              int where, int size, u32 *val)
+{
+       return pnv_pci_cfg_read(bus, devfn, where,
+                               size, val, true);
+}
+
+static int pnv_pci_write_config(struct pci_bus *bus,
+                               unsigned int devfn,
+                               int where, int size,
+                               u32 val)
+{
+       return pnv_pci_cfg_write(bus, devfn, where,
+                                size, val, true);
+}
+
 struct pci_ops pnv_pci_ops = {
        .read = pnv_pci_read_config,
        .write = pnv_pci_write_config,
diff --git a/arch/powerpc/platforms/powernv/pci.h 
b/arch/powerpc/platforms/powernv/pci.h
index a281a1c..8624f8f 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -187,6 +187,10 @@ extern struct pci_ops pnv_pci_ops;
 extern struct pnv_eeh_ops ioda_eeh_ops;
 #endif
 
+extern int pnv_pci_cfg_read(struct pci_bus *bus, unsigned int devfn,
+                           int where, int size, u32 *val, bool check);
+extern int pnv_pci_cfg_write(struct pci_bus *bus, unsigned int devfn,
+                            int where, int size, u32 val, bool check);
 extern void pnv_pci_setup_iommu_table(struct iommu_table *tbl,
                                      void *tce_mem, u64 tce_size,
                                      u64 dma_offset);
-- 
1.7.5.4

_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

Reply via email to