[PATCH 3/3] powerpc/powernv: Issue fundamental reset if required
Gavin Shan
gwshan at linux.vnet.ibm.com
Thu Dec 4 16:50:53 AEDT 2014
Function pnv_pci_reset_secondary_bus() is used to reset specified
PCI bus, which is leaded by root complex or PCI bridge. That means
the function shouldn't be called on PCI root bus and the patch
removes the logic for the case.
Also, some adapters may require fundamental reset to reload their
firmwares. Otherwise, they will fail to load their firmwares and
those adapters can't work properly after reset, as being reported
in VFIO pass-through scenario. The patch checks the reset type
required by the child adapters of the PCI bus and issue fundamental
reset if necessary.
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 78d94df..cf38781 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -636,18 +636,34 @@ static int ioda_eeh_bridge_reset(struct pci_dev *dev, int option)
return (rc == OPAL_SUCCESS) ? 0 : -EIO;
}
-void pnv_pci_reset_secondary_bus(struct pci_dev *dev)
+static int pnv_pci_dev_reset_type(struct pci_dev *pdev, void *data)
{
- struct pci_controller *hose;
+ int *freset = data;
- 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);
+ /*
+ * Stop the iteration immediately if any one PCI
+ * device requires fundamental reset
+ */
+ *freset |= pdev->needs_freset;
+ return *freset;
+}
+
+void pnv_pci_reset_secondary_bus(struct pci_dev *pdev)
+{
+ int option = EEH_RESET_HOT;
+ int freset = 0;
+
+ /* Check if we need issue fundamental reset */
+ if (pdev->subordinate) {
+ pci_walk_bus(pdev->subordinate,
+ pnv_pci_dev_reset_type, &freset);
+ if (freset)
+ option = EEH_RESET_FUNDAMENTAL;
}
+
+ /* Issue required reset type */
+ ioda_eeh_bridge_reset(pdev, option);
+ ioda_eeh_bridge_reset(pdev, EEH_RESET_DEACTIVATE);
}
/**
--
1.8.3.2
More information about the Linuxppc-dev
mailing list