@@ -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);
}
/**
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@linux.vnet.ibm.com> --- arch/powerpc/platforms/powernv/eeh-ioda.c | 34 +++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 9 deletions(-)