[PATCH 4/5] powerpc/powernv: Issue fundamental reset if required

Gavin Shan gwshan at linux.vnet.ibm.com
Tue Nov 25 09:38:46 AEDT 2014


pnv_pci_reset_secondary_bus() is the backend for resetting the
secondary bus for the specified PCI bridge. We always issue hot
reset, which isn't enough for some devices who requires fundamental
reset explicitly. The patch switches to fundamental reset if the
devices ask for that.

Signed-off-by: Gavin Shan <gwshan at linux.vnet.ibm.com>
---
 arch/powerpc/platforms/powernv/eeh-ioda.c | 34 +++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index d02a696..4bf2fb5 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -650,18 +650,34 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
 	return 0;
 }
 
+static int pnv_pci_dev_reset_type(struct pci_dev *pdev, void *data)
+{
+	int *freset = data;
+
+	/*
+	 * Stop the iteration immediately if any one
+	 * PCI device requires fundamental reset
+	 */
+	*freset |= pdev->needs_freset;
+	return *freset;
+}
+
+/*
+ * When the function is called, there should have
+ * valid bridge. We don't need cover root bus here
+ */
 void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
 {
-	struct pci_controller *hose;
+	int option = EEH_RESET_HOT;
+	int freset = 0;
 
-	if (pci_is_root_bus(dev->bus)) {
-		hose = pci_bus_to_host(dev->bus);
-		ioda_eeh_phb_reset(hose, EEH_RESET_HOT);
-		ioda_eeh_phb_reset(hose, EEH_RESET_DEACTIVATE);
-	} else {
-		ioda_eeh_bridge_reset(dev, EEH_RESET_HOT);
-		ioda_eeh_bridge_reset(dev, EEH_RESET_DEACTIVATE);
-	}
+	/* Need fundamental reset ? */
+	pci_walk_bus(dev->subordinate, pnv_pci_dev_reset_type, &freset);
+	if (freset)
+		option = EEH_RESET_FUNDAMENTAL;
+
+	ioda_eeh_bridge_reset(dev, option);
+	ioda_eeh_bridge_reset(dev, EEH_RESET_DEACTIVATE);
 }
 
 /**
-- 
1.8.3.2



More information about the Linuxppc-dev mailing list