static int eeh_reset_device (struct pci_dn *pe_dn, struct pci_bus *bus) { int cnt, rc; /* pcibios will clear the counter; save the value */ cnt = pe_dn->eeh_freeze_count; if (bus) pcibios_remove_pci_devices(bus); /* Reset the pci controller. (Asserts RST#; resets config space). * Reconfigure bridges and devices. Don't try to bring the system * up if the reset failed for some reason. */ rc = rtas_set_slot_reset(pe_dn); if (rc) return rc; /* New-style config addrs might be shared across multiple devices, * Walk over all functions on this device */ if (pe_dn->eeh_pe_config_addr) { struct device_node *pe = pe_dn->node; pe = pe->parent->child; while (pe) { struct pci_dn *ppe = PCI_DN(pe); if (pe_dn->eeh_pe_config_addr == ppe->eeh_pe_config_addr) { rtas_configure_bridge(ppe); eeh_restore_bars(ppe); } pe = pe->sibling; } } else { rtas_configure_bridge(pe_dn); eeh_restore_bars(pe_dn); } /* Give the system 5 seconds to finish running the user-space * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, * this is a hack, but if we don't do this, and try to bring * the device up before the scripts have taken it down, * potentially weird things happen. */ if (bus) { ssleep (5); pcibios_add_pci_devices(bus); } pe_dn->eeh_freeze_count = cnt; return 0; }
/** * eeh_reset_device - Perform actual reset of a pci slot * @edev: PE associated EEH device * @bus: PCI bus corresponding to the isolcated slot * * This routine must be called to do reset on the indicated PE. * During the reset, udev might be invoked because those affected * PCI devices will be removed and then added. */ static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus) { struct device_node *dn; int cnt, rc; /* pcibios will clear the counter; save the value */ cnt = edev->freeze_count; if (bus) pcibios_remove_pci_devices(bus); /* Reset the pci controller. (Asserts RST#; resets config space). * Reconfigure bridges and devices. Don't try to bring the system * up if the reset failed for some reason. */ rc = eeh_reset_pe(edev); if (rc) return rc; /* Walk over all functions on this device. */ dn = eeh_dev_to_of_node(edev); if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent)) dn = dn->parent->child; while (dn) { struct eeh_dev *pedev = of_node_to_eeh_dev(dn); /* On Power4, always true because eeh_pe_config_addr=0 */ if (edev->pe_config_addr == pedev->pe_config_addr) { eeh_ops->configure_bridge(dn); eeh_restore_bars(pedev); } dn = dn->sibling; } /* Give the system 5 seconds to finish running the user-space * hotplug shutdown scripts, e.g. ifdown for ethernet. Yes, * this is a hack, but if we don't do this, and try to bring * the device up before the scripts have taken it down, * potentially weird things happen. */ if (bus) { ssleep(5); pcibios_add_pci_devices(bus); } edev->freeze_count = cnt; return 0; }
/** * eeh_restore_bars - restore the PCI config space info * * This routine performs a recursive walk to the children * of this device as well. */ void eeh_restore_bars(struct pci_dn *pdn) { struct device_node *dn; if (!pdn) return; if ((pdn->eeh_mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(pdn->class_code)) __restore_bars (pdn); dn = pdn->node->child; while (dn) { eeh_restore_bars (PCI_DN(dn)); dn = dn->sibling; } }
static int eeh_reset_device(struct eeh_dev *edev, struct pci_bus *bus) { struct device_node *dn; int cnt, rc; cnt = edev->freeze_count; if (bus) pcibios_remove_pci_devices(bus); rc = eeh_reset_pe(edev); if (rc) return rc; dn = eeh_dev_to_of_node(edev); if (!pcibios_find_pci_bus(dn) && of_node_to_eeh_dev(dn->parent)) dn = dn->parent->child; while (dn) { struct eeh_dev *pedev = of_node_to_eeh_dev(dn); if (edev->pe_config_addr == pedev->pe_config_addr) { eeh_ops->configure_bridge(dn); eeh_restore_bars(pedev); } dn = dn->sibling; } if (bus) { ssleep(5); pcibios_add_pci_devices(bus); } edev->freeze_count = cnt; return 0; }