int false_positives;            /* Times of reported #ff's      */
        atomic_t pass_dev_cnt;          /* Count of passed through devs */
        struct eeh_pe *parent;          /* Parent PE                    */
+       void *data;                     /* PE auxillary data            */
        struct list_head child_list;    /* Link PE to the child list    */
        struct list_head edevs;         /* Link list of EEH devices     */
        struct list_head child;         /* Child PEs                    */
 #define EEH_MAX_ALLOWED_FREEZES 5
 
 typedef void *(*eeh_traverse_func)(void *data, void *flag);
+void eeh_set_pe_aux_size(int size);
 int eeh_phb_pe_create(struct pci_controller *phb);
 struct eeh_pe *eeh_phb_pe_get(struct pci_controller *phb);
 struct eeh_pe *eeh_pe_get(struct eeh_dev *edev);
 
 #include <asm/pci-bridge.h>
 #include <asm/ppc-pci.h>
 
+static int eeh_pe_aux_size = 0;
 static LIST_HEAD(eeh_phb_pe);
 
+/**
+ * eeh_set_pe_aux_size - Set PE auxillary data size
+ * @size: PE auxillary data size
+ *
+ * Set PE auxillary data size
+ */
+void eeh_set_pe_aux_size(int size)
+{
+       if (size < 0)
+               return;
+
+       eeh_pe_aux_size = size;
+}
+
 /**
  * eeh_pe_alloc - Allocate PE
  * @phb: PCI controller
 static struct eeh_pe *eeh_pe_alloc(struct pci_controller *phb, int type)
 {
        struct eeh_pe *pe;
+       size_t alloc_size;
+
+       alloc_size = sizeof(struct eeh_pe);
+       if (eeh_pe_aux_size) {
+               alloc_size = ALIGN(alloc_size, cache_line_size());
+               alloc_size += eeh_pe_aux_size;
+       }
 
        /* Allocate PHB PE */
-       pe = kzalloc(sizeof(struct eeh_pe), GFP_KERNEL);
+       pe = kzalloc(alloc_size, GFP_KERNEL);
        if (!pe) return NULL;
 
        /* Initialize PHB PE */
        INIT_LIST_HEAD(&pe->child);
        INIT_LIST_HEAD(&pe->edevs);
 
+       pe->data = (void *)pe + ALIGN(sizeof(struct eeh_pe),
+                                     cache_line_size());
        return pe;
 }
 
 
        return ret;
 }
 
-static void ioda_eeh_phb_diag(struct pci_controller *hose)
+static void ioda_eeh_phb_diag(struct eeh_pe *pe)
 {
-       struct pnv_phb *phb = hose->private_data;
+       struct pnv_phb *phb = pe->phb->private_data;
        long rc;
 
-       rc = opal_pci_get_phb_diag_data2(phb->opal_id, phb->diag.blob,
+       rc = opal_pci_get_phb_diag_data2(phb->opal_id, pe->data,
                                         PNV_PCI_DIAG_BUF_SIZE);
-       if (rc != OPAL_SUCCESS) {
+       if (rc != OPAL_SUCCESS)
                pr_warn("%s: Failed to get diag-data for PHB#%x (%ld)\n",
-                       __func__, hose->global_number, rc);
-               return;
-       }
-
-       pnv_pci_dump_phb_diag_data(hose, phb->diag.blob);
+                       __func__, pe->phb->global_number, rc);
 }
 
 /**
                        result |= EEH_STATE_DMA_ENABLED;
                } else if (!(pe->state & EEH_PE_ISOLATED)) {
                        eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
-                       ioda_eeh_phb_diag(hose);
+                       ioda_eeh_phb_diag(pe);
                }
 
                return result;
            (EEH_STATE_MMIO_ACTIVE | EEH_STATE_DMA_ACTIVE) &&
            !(pe->state & EEH_PE_ISOLATED)) {
                eeh_pe_state_mark(pe, EEH_PE_ISOLATED);
-               ioda_eeh_phb_diag(hose);
+               ioda_eeh_phb_diag(pe);
        }
 
        return result;
        return ret;
 }
 
+/**
+ * ioda_eeh_get_log - Retrieve error log
+ * @pe: frozen PE
+ * @severity: permanent or temporary error
+ * @drv_log: device driver log
+ * @len: length of device driver log
+ *
+ * Retrieve error log, which contains log from device driver
+ * and firmware.
+ */
+int ioda_eeh_get_log(struct eeh_pe *pe, int severity,
+                    char *drv_log, unsigned long len)
+{
+       pnv_pci_dump_phb_diag_data(pe->phb, pe->data);
+
+       return 0;
+}
+
 /**
  * ioda_eeh_configure_bridge - Configure the PCI bridges for the indicated PE
  * @pe: EEH PE
                                        "detected, location: %s\n",
                                        hose->global_number,
                                        eeh_pe_loc_get(phb_pe));
-                               ioda_eeh_phb_diag(hose);
+                               ioda_eeh_phb_diag(phb_pe);
+                               pnv_pci_dump_phb_diag_data(hose, phb_pe->data);
                                ret = EEH_NEXT_ERR_NONE;
                        }
 
                    ret == EEH_NEXT_ERR_FENCED_PHB) &&
                    !((*pe)->state & EEH_PE_ISOLATED)) {
                        eeh_pe_state_mark(*pe, EEH_PE_ISOLATED);
-                       ioda_eeh_phb_diag(hose);
+                       ioda_eeh_phb_diag(*pe);
                }
 
                /*
        .set_option             = ioda_eeh_set_option,
        .get_state              = ioda_eeh_get_state,
        .reset                  = ioda_eeh_reset,
+       .get_log                = ioda_eeh_get_log,
        .configure_bridge       = ioda_eeh_configure_bridge,
        .next_error             = ioda_eeh_next_error
 };
 
  * Retrieve the temporary or permanent error from the PE.
  */
 static int powernv_eeh_get_log(struct eeh_pe *pe, int severity,
-                       char *drv_log, unsigned long len)
+                              char *drv_log, unsigned long len)
 {
        struct pci_controller *hose = pe->phb;
        struct pnv_phb *phb = hose->private_data;
 {
        int ret = -EINVAL;
 
+       eeh_set_pe_aux_size(PNV_PCI_DIAG_BUF_SIZE);
        ret = eeh_ops_register(&powernv_eeh_ops);
        if (!ret)
                pr_info("EEH: PowerNV platform initialized\n");