The skiboot firmware might provide the capability of resetting PCI
slot by property "ibm,reset-by-firmware" on the PCI slot associated
device node. The patch checks on the property and route the reset
to firmware if the property exists. Otherwise, we fail back to the
old path as before.

Signed-off-by: Gavin Shan <gws...@linux.vnet.ibm.com>
---
v5:
  * Derived from PATCH[v4 09/21]
---
 arch/powerpc/platforms/powernv/eeh-powernv.c | 44 +++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c 
b/arch/powerpc/platforms/powernv/eeh-powernv.c
index 4fd8f15..4feb533 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -841,7 +841,7 @@ out:
        return 0;
 }
 
-static int pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
+static int __pnv_eeh_bridge_reset(struct pci_dev *dev, int option)
 {
        struct pci_dn *pdn = pci_get_pdn_by_devfn(dev->bus, dev->devfn);
        struct eeh_dev *edev = pdn_to_eeh_dev(pdn);
@@ -892,6 +892,48 @@ static int pnv_eeh_bridge_reset(struct pci_dev *dev, int 
option)
        return 0;
 }
 
+static int pnv_eeh_bridge_reset(struct pci_dev *pdev, int option)
+{
+       struct pci_controller *hose;
+       struct pnv_phb *phb;
+       struct device_node *dn = pdev ? pci_device_to_OF_node(pdev) : NULL;
+       uint64_t id = (0x1ul << 60);
+       uint8_t scope;
+       int64_t rc;
+
+       /*
+        * If the firmware can't handle it, we will issue hot reset
+        * on the secondary bus despite the requested reset type.
+        */
+       if (!dn || !of_get_property(dn, "ibm,reset-by-firmware", NULL))
+               return __pnv_eeh_bridge_reset(pdev, option);
+
+       /* The firmware can handle the request */
+       switch (option) {
+       case EEH_RESET_HOT:
+               scope = OPAL_RESET_PCI_HOT;
+               break;
+       case EEH_RESET_FUNDAMENTAL:
+               scope = OPAL_RESET_PCI_FUNDAMENTAL;
+               break;
+       case EEH_RESET_DEACTIVATE:
+               return 0;
+       default:
+               dev_warn(&pdev->dev, "%s: Unsupported reset %d\n",
+                        __func__, option);
+               return -EINVAL;
+       }
+
+       hose = pci_bus_to_host(pdev->bus);
+       phb = hose->private_data;
+       id |= (pdev->bus->number << 24) | (pdev->devfn << 16) | phb->opal_id;
+       rc = opal_pci_reset(id, scope, OPAL_ASSERT_RESET);
+       if (rc > 0)
+               rc = pnv_eeh_poll(id);
+
+       return (rc == OPAL_SUCCESS) ? 0 : -EIO;
+}
+
 static void pnv_eeh_wait_for_pending(struct pci_dn *pdn, int pos,
                                     u16 mask, bool af_flr_rst)
 {
-- 
2.1.0

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

Reply via email to