#define EEH_PE_RECOVERING      (1 << 1)        /* Recovering PE        */
 #define EEH_PE_PHB_DEAD                (1 << 2)        /* Dead PHB             */
 
+#define EEH_PE_KEEP            (1 << 8)        /* Keep PE on hotplug   */
+
 struct eeh_pe {
        int type;                       /* PE type: PHB/Bus/Device      */
        int state;                      /* PE EEH dependent mode        */
 struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb);
 struct eeh_pe *eeh_pe_get(struct eeh_dev *edev);
 int eeh_add_to_parent_pe(struct eeh_dev *edev);
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe);
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev);
 void eeh_pe_update_time_stamp(struct eeh_pe *pe);
 void *eeh_pe_dev_traverse(struct eeh_pe *root,
                eeh_traverse_func fn, void *flag);
 void eeh_add_device_late(struct pci_dev *);
 void eeh_add_device_tree_late(struct pci_bus *);
 void eeh_add_sysfs_files(struct pci_bus *);
-void eeh_remove_device(struct pci_dev *, int);
-void eeh_remove_bus_device(struct pci_dev *, int);
+void eeh_remove_device(struct pci_dev *);
 
 /**
  * EEH_POSSIBLE_ERROR() -- test for possible MMIO failure.
 
 static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
 
-static inline void eeh_remove_device(struct pci_dev *dev, int purge_pe) { }
-
-static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
+static inline void eeh_remove_device(struct pci_dev *dev) { }
 
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
 
 extern struct pci_bus *pcibios_find_pci_bus(struct device_node *dn);
 
 /** Remove all of the PCI devices under this bus */
-extern void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe);
 extern void pcibios_remove_pci_devices(struct pci_bus *bus);
 
 /** Discover new pci devices under this bus, and add them */
 
 /**
  * eeh_remove_device - Undo EEH setup for the indicated pci device
  * @dev: pci device to be removed
- * @purge_pe: remove the PE or not
  *
  * This routine should be called when a device is removed from
  * a running system (e.g. by hotplug or dlpar).  It unregisters
  * this device will no longer be detected after this call; thus,
  * i/o errors affecting this slot may leave this device unusable.
  */
-void eeh_remove_device(struct pci_dev *dev, int purge_pe)
+void eeh_remove_device(struct pci_dev *dev)
 {
        struct eeh_dev *edev;
 
        edev->pdev = NULL;
        dev->dev.archdata.edev = NULL;
 
-       eeh_rmv_from_parent_pe(edev, purge_pe);
+       eeh_rmv_from_parent_pe(edev);
        eeh_addr_cache_rmv_dev(dev);
        eeh_sysfs_remove_device(dev);
 }
 
-/**
- * eeh_remove_bus_device - Undo EEH setup for the indicated PCI device
- * @dev: PCI device
- * @purge_pe: remove the corresponding PE or not
- *
- * This routine must be called when a device is removed from the
- * running system through hotplug or dlpar. The corresponding
- * PCI address cache will be removed.
- */
-void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe)
-{
-       struct pci_bus *bus = dev->subordinate;
-       struct pci_dev *child, *tmp;
-
-       eeh_remove_device(dev, purge_pe);
-
-       if (bus && dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
-               list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
-                        eeh_remove_bus_device(child, purge_pe);
-       }
-}
-EXPORT_SYMBOL_GPL(eeh_remove_bus_device);
-
 static int proc_eeh_show(struct seq_file *m, void *v)
 {
        if (0 == eeh_subsystem_enabled) {
 
         * devices are expected to be attached soon when calling
         * into pcibios_add_pci_devices().
         */
-       if (bus)
-               __pcibios_remove_pci_devices(bus, 0);
+       if (bus) {
+               eeh_pe_state_mark(pe, EEH_PE_KEEP);
+               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
        if (bus) {
                ssleep(5);
                pcibios_add_pci_devices(bus);
+               eeh_pe_state_clear(pe, EEH_PE_KEEP);
        }
 
        pe->tstamp = tstamp;
 
                while (parent) {
                        if (!(parent->type & EEH_PE_INVALID))
                                break;
-                       parent->type &= ~EEH_PE_INVALID;
+                       parent->type &= ~(EEH_PE_INVALID | EEH_PE_KEEP);
                        parent = parent->parent;
                }
                pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
 /**
  * eeh_rmv_from_parent_pe - Remove one EEH device from the associated PE
  * @edev: EEH device
- * @purge_pe: remove PE or not
  *
  * The PE hierarchy tree might be changed when doing PCI hotplug.
  * Also, the PCI devices or buses could be removed from the system
  * during EEH recovery. So we have to call the function remove the
  * corresponding PE accordingly if necessary.
  */
-int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
+int eeh_rmv_from_parent_pe(struct eeh_dev *edev)
 {
        struct eeh_pe *pe, *parent, *child;
        int cnt;
                if (pe->type & EEH_PE_PHB)
                        break;
 
-               if (purge_pe) {
+               if (!(pe->state & EEH_PE_KEEP)) {
                        if (list_empty(&pe->edevs) &&
                            list_empty(&pe->child_list)) {
                                list_del(&pe->child);
 
  */
 void pcibios_release_device(struct pci_dev *dev)
 {
-       eeh_remove_device(dev, 1);
+       eeh_remove_device(dev);
 }
 
 /**
- * __pcibios_remove_pci_devices - remove all devices under this bus
+ * pcibios_remove_pci_devices - remove all devices under this bus
  * @bus: the indicated PCI bus
- * @purge_pe: destroy the PE on removal of PCI devices
  *
  * Remove all of the PCI devices under this bus both from the
  * linux pci device tree, and from the powerpc EEH address cache.
- * By default, the corresponding PE will be destroied during the
- * normal PCI hotplug path. For PCI hotplug during EEH recovery,
- * the corresponding PE won't be destroied and deallocated.
  */
-void __pcibios_remove_pci_devices(struct pci_bus *bus, int purge_pe)
+void pcibios_remove_pci_devices(struct pci_bus *bus)
 {
        struct pci_dev *dev, *tmp;
        struct pci_bus *child_bus;
 
        /* First go down child busses */
        list_for_each_entry(child_bus, &bus->children, node)
-               __pcibios_remove_pci_devices(child_bus, purge_pe);
+               pcibios_remove_pci_devices(child_bus);
 
        pr_debug("PCI: Removing devices on bus %04x:%02x\n",
                 pci_domain_nr(bus),  bus->number);
        list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
-               pr_debug("     * Removing %s...\n", pci_name(dev));
-               eeh_remove_bus_device(dev, purge_pe);
+               pr_debug("   Removing %s...\n", pci_name(dev));
                pci_stop_and_remove_bus_device(dev);
        }
 }
 
-/**
- * pcibios_remove_pci_devices - remove all devices under this bus
- * @bus: the indicated PCI bus
- *
- * Remove all of the PCI devices under this bus both from the
- * linux pci device tree, and from the powerpc EEH address cache.
- */
-void pcibios_remove_pci_devices(struct pci_bus *bus)
-{
-       __pcibios_remove_pci_devices(bus, 1);
-}
 EXPORT_SYMBOL_GPL(pcibios_remove_pci_devices);
 
 /**