int __devinit eeh_phb_pe_create(struct pci_controller *phb);
 int eeh_add_to_parent_pe(struct eeh_dev *edev);
 int eeh_rmv_from_parent_pe(struct eeh_dev *edev);
+void *eeh_pe_dev_traverse(struct eeh_pe *root,
+               eeh_traverse_func fn, void *flag);
+void eeh_pe_restore_bars(struct eeh_pe *pe);
 
 void * __devinit eeh_dev_init(struct device_node *dn, void *data);
 void __devinit eeh_dev_phb_init_dynamic(struct pci_controller *phb);
 
 void eeh_slot_error_detail(struct eeh_dev *edev, int severity);
 int eeh_pci_enable(struct eeh_dev *edev, int function);
 int eeh_reset_pe(struct eeh_dev *);
-void eeh_restore_bars(struct eeh_dev *);
 int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
 int rtas_read_config(struct pci_dn *, int where, int size, u32 *val);
 void eeh_pe_state_mark(struct eeh_pe *pe, int state);
 
        return -1;
 }
 
-/** Save and restore of PCI BARs
- *
- * Although firmware will set up BARs during boot, it doesn't
- * set up device BAR's after a device reset, although it will,
- * if requested, set up bridge configuration. Thus, we need to
- * configure the PCI devices ourselves.  
- */
-
-/**
- * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
- * @edev: PCI device associated EEH device
- *
- * Loads the PCI configuration space base address registers,
- * the expansion ROM base address, the latency timer, and etc.
- * from the saved values in the device node.
- */
-static inline void eeh_restore_one_device_bars(struct eeh_dev *edev)
-{
-       int i;
-       u32 cmd;
-       struct device_node *dn = eeh_dev_to_of_node(edev);
-
-       if (!edev->phb)
-               return;
-
-       for (i=4; i<10; i++) {
-               eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
-       }
-
-       /* 12 == Expansion ROM Address */
-       eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
-
-#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
-#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
-
-       eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
-                   SAVED_BYTE(PCI_CACHE_LINE_SIZE));
-
-       eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
-                   SAVED_BYTE(PCI_LATENCY_TIMER));
-
-       /* max latency, min grant, interrupt pin and line */
-       eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
-
-       /* Restore PERR & SERR bits, some devices require it,
-        * don't touch the other command bits
-        */
-       eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
-       if (edev->config_space[1] & PCI_COMMAND_PARITY)
-               cmd |= PCI_COMMAND_PARITY;
-       else
-               cmd &= ~PCI_COMMAND_PARITY;
-       if (edev->config_space[1] & PCI_COMMAND_SERR)
-               cmd |= PCI_COMMAND_SERR;
-       else
-               cmd &= ~PCI_COMMAND_SERR;
-       eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
-}
-
-/**
- * eeh_restore_bars - Restore the PCI config space info
- * @edev: EEH device
- *
- * This routine performs a recursive walk to the children
- * of this device as well.
- */
-void eeh_restore_bars(struct eeh_dev *edev)
-{
-       struct device_node *dn;
-       if (!edev)
-               return;
-       
-       if ((edev->mode & EEH_MODE_SUPPORTED) && !IS_BRIDGE(edev->class_code))
-               eeh_restore_one_device_bars(edev);
-
-       for_each_child_of_node(eeh_dev_to_of_node(edev), dn)
-               eeh_restore_bars(of_node_to_eeh_dev(dn));
-}
-
 /**
  * eeh_save_bars - Save device bars
  * @edev: PCI device associated EEH device
 
        return NULL;
 }
 
+/**
+ * eeh_pe_dev_traverse - Traverse the devices from the PE
+ * @root: EEH PE
+ * @fn: function callback
+ * @flag: extra parameter to callback
+ *
+ * The function is used to traverse the devices of the specified
+ * PE and its child PEs.
+ */
+void *eeh_pe_dev_traverse(struct eeh_pe *root,
+               eeh_traverse_func fn, void *flag)
+{
+       struct eeh_pe *pe;
+       struct eeh_dev *edev;
+       void *ret;
+
+       if (!root) {
+               pr_warning("%s: Invalid PE %p\n", __func__, root);
+               return NULL;
+       }
+
+       /* Traverse root PE */
+       for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
+               eeh_pe_for_each_dev(pe, edev) {
+                       ret = fn(edev, flag);
+                       if (ret) return ret;
+               }
+       }
+
+       return NULL;
+}
+
 /**
  * __eeh_pe_get - Check the PE address
  * @data: EEH PE
 {
        eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
 }
+
+/**
+ * eeh_restore_one_device_bars - Restore the Base Address Registers for one device
+ * @data: EEH device
+ * @flag: Unused
+ *
+ * Loads the PCI configuration space base address registers,
+ * the expansion ROM base address, the latency timer, and etc.
+ * from the saved values in the device node.
+ */
+static void *eeh_restore_one_device_bars(void *data, void *flag)
+{
+       int i;
+       u32 cmd;
+       struct eeh_dev *edev = (struct eeh_dev *)data;
+       struct device_node *dn = eeh_dev_to_of_node(edev);
+
+       for (i = 4; i < 10; i++)
+               eeh_ops->write_config(dn, i*4, 4, edev->config_space[i]);
+       /* 12 == Expansion ROM Address */
+       eeh_ops->write_config(dn, 12*4, 4, edev->config_space[12]);
+
+#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
+#define SAVED_BYTE(OFF) (((u8 *)(edev->config_space))[BYTE_SWAP(OFF)])
+
+       eeh_ops->write_config(dn, PCI_CACHE_LINE_SIZE, 1,
+               SAVED_BYTE(PCI_CACHE_LINE_SIZE));
+       eeh_ops->write_config(dn, PCI_LATENCY_TIMER, 1,
+               SAVED_BYTE(PCI_LATENCY_TIMER));
+
+       /* max latency, min grant, interrupt pin and line */
+       eeh_ops->write_config(dn, 15*4, 4, edev->config_space[15]);
+
+       /*
+        * Restore PERR & SERR bits, some devices require it,
+        * don't touch the other command bits
+        */
+       eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
+       if (edev->config_space[1] & PCI_COMMAND_PARITY)
+               cmd |= PCI_COMMAND_PARITY;
+       else
+               cmd &= ~PCI_COMMAND_PARITY;
+       if (edev->config_space[1] & PCI_COMMAND_SERR)
+               cmd |= PCI_COMMAND_SERR;
+       else
+               cmd &= ~PCI_COMMAND_SERR;
+       eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
+
+       return NULL;
+}
+
+/**
+ * eeh_pe_restore_bars - Restore the PCI config space info
+ * @pe: EEH PE
+ *
+ * This routine performs a recursive walk to the children
+ * of this device as well.
+ */
+void eeh_pe_restore_bars(struct eeh_pe *pe)
+{
+       eeh_pe_dev_traverse(pe, eeh_restore_one_device_bars, NULL);
+}