Merge branch 'mpic' into next
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 2893e8f..a4b28f1 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -109,6 +109,14 @@
 #define OPAL_PCI_MAP_PE_DMA_WINDOW		44
 #define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL		45
 #define OPAL_PCI_RESET				49
+#define OPAL_PCI_GET_HUB_DIAG_DATA		50
+#define OPAL_PCI_GET_PHB_DIAG_DATA		51
+#define OPAL_PCI_FENCE_PHB			52
+#define OPAL_PCI_REINIT				53
+#define OPAL_PCI_MASK_PE_ERROR			54
+#define OPAL_SET_SLOT_LED_STATUS		55
+#define OPAL_GET_EPOW_STATUS			56
+#define OPAL_SET_SYSTEM_ATTENTION_LED		57
 
 #ifndef __ASSEMBLY__
 
@@ -169,7 +177,11 @@
 	OPAL_EVENT_NVRAM = 0x2,
 	OPAL_EVENT_RTC = 0x4,
 	OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
-	OPAL_EVENT_CONSOLE_INPUT = 0x10
+	OPAL_EVENT_CONSOLE_INPUT = 0x10,
+	OPAL_EVENT_ERROR_LOG_AVAIL = 0x20,
+	OPAL_EVENT_ERROR_LOG = 0x40,
+	OPAL_EVENT_EPOW = 0x80,
+	OPAL_EVENT_LED_STATUS = 0x100
 };
 
 /* Machine check related definitions */
@@ -258,13 +270,49 @@
 	OPAL_MAP_PE = 1
 };
 
+enum OpalPeltvAction {
+	OPAL_REMOVE_PE_FROM_DOMAIN = 0,
+	OPAL_ADD_PE_TO_DOMAIN = 1
+};
+
+enum OpalMveEnableAction {
+	OPAL_DISABLE_MVE = 0,
+	OPAL_ENABLE_MVE = 1
+};
+
 enum OpalPciResetAndReinitScope {
 	OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
 	OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
-	OPAL_PCI_IODA_RESET = 6,
+	OPAL_PCI_IODA_TABLE_RESET = 6,
 };
 
-enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+enum OpalPciResetState {
+	OPAL_DEASSERT_RESET = 0,
+	OPAL_ASSERT_RESET = 1
+};
+
+enum OpalPciMaskAction {
+	OPAL_UNMASK_ERROR_TYPE = 0,
+	OPAL_MASK_ERROR_TYPE = 1
+};
+
+enum OpalSlotLedType {
+	OPAL_SLOT_LED_ID_TYPE = 0,
+	OPAL_SLOT_LED_FAULT_TYPE = 1
+};
+
+enum OpalLedAction {
+	OPAL_TURN_OFF_LED = 0,
+	OPAL_TURN_ON_LED = 1,
+	OPAL_QUERY_LED_STATE_AFTER_BUSY = 2
+};
+
+enum OpalEpowStatus {
+	OPAL_EPOW_NONE = 0,
+	OPAL_EPOW_UPS = 1,
+	OPAL_EPOW_OVER_AMBIENT_TEMP = 2,
+	OPAL_EPOW_OVER_INTERNAL_TEMP = 3
+};
 
 struct opal_machine_check_event {
 	enum OpalMCE_Version	version:8;	/* 0x00 */
@@ -314,8 +362,74 @@
 	} u;
 };
 
+/**
+ * This structure defines the overlay which will be used to store PHB error
+ * data upon request.
+ */
+enum {
+	OPAL_P7IOC_NUM_PEST_REGS = 128,
+};
+
+struct OpalIoP7IOCPhbErrorData {
+	uint32_t brdgCtl;
+
+	// P7IOC utl regs
+	uint32_t portStatusReg;
+	uint32_t rootCmplxStatus;
+	uint32_t busAgentStatus;
+
+	// P7IOC cfg regs
+	uint32_t deviceStatus;
+	uint32_t slotStatus;
+	uint32_t linkStatus;
+	uint32_t devCmdStatus;
+	uint32_t devSecStatus;
+
+	// cfg AER regs
+	uint32_t rootErrorStatus;
+	uint32_t uncorrErrorStatus;
+	uint32_t corrErrorStatus;
+	uint32_t tlpHdr1;
+	uint32_t tlpHdr2;
+	uint32_t tlpHdr3;
+	uint32_t tlpHdr4;
+	uint32_t sourceId;
+
+	uint32_t rsv3;
+
+	// Record data about the call to allocate a buffer.
+	uint64_t errorClass;
+	uint64_t correlator;
+
+	//P7IOC MMIO Error Regs
+	uint64_t p7iocPlssr;                // n120
+	uint64_t p7iocCsr;                  // n110
+	uint64_t lemFir;                    // nC00
+	uint64_t lemErrorMask;              // nC18
+	uint64_t lemWOF;                    // nC40
+	uint64_t phbErrorStatus;            // nC80
+	uint64_t phbFirstErrorStatus;       // nC88
+	uint64_t phbErrorLog0;              // nCC0
+	uint64_t phbErrorLog1;              // nCC8
+	uint64_t mmioErrorStatus;           // nD00
+	uint64_t mmioFirstErrorStatus;      // nD08
+	uint64_t mmioErrorLog0;             // nD40
+	uint64_t mmioErrorLog1;             // nD48
+	uint64_t dma0ErrorStatus;           // nD80
+	uint64_t dma0FirstErrorStatus;      // nD88
+	uint64_t dma0ErrorLog0;             // nDC0
+	uint64_t dma0ErrorLog1;             // nDC8
+	uint64_t dma1ErrorStatus;           // nE00
+	uint64_t dma1FirstErrorStatus;      // nE08
+	uint64_t dma1ErrorLog0;             // nE40
+	uint64_t dma1ErrorLog1;             // nE48
+	uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS];
+	uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS];
+};
+
 typedef struct oppanel_line {
-	/* XXX */
+	const char * 	line;
+	uint64_t 	line_len;
 } oppanel_line_t;
 
 /* API functions */
@@ -413,6 +527,15 @@
 					uint64_t pci_mem_size);
 int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
 
+int64_t opal_pci_get_hub_diag_data(uint64_t hub_id, void *diag_buffer, uint64_t diag_buffer_len);
+int64_t opal_pci_get_phb_diag_data(uint64_t phb_id, void *diag_buffer, uint64_t diag_buffer_len);
+int64_t opal_pci_fence_phb(uint64_t phb_id);
+int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope);
+int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action);
+int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action);
+int64_t opal_get_epow_status(uint64_t *status);
+int64_t opal_set_system_attention_led(uint8_t led_action);
+
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
 
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 49c3de5..1c92013 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -184,8 +184,6 @@
 extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
 extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
 
-extern int pci_read_irq_line(struct pci_dev *dev);
-
 struct file;
 extern pgprot_t	pci_phys_mem_access_prot(struct file *file,
 					 unsigned long pfn,
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 9bffc02..fa4a573 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -214,7 +214,7 @@
  * If the interrupt is used, then gets the interrupt line from the
  * openfirmware and sets it in the pci_dev and pci_config line.
  */
-int pci_read_irq_line(struct pci_dev *pci_dev)
+static int pci_read_irq_line(struct pci_dev *pci_dev)
 {
 	struct of_irq oirq;
 	unsigned int virq;
@@ -283,7 +283,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(pci_read_irq_line);
 
 /*
  * Platform support for /proc/bus/pci/X/Y mmap()s,
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index cc58486..f4f9f2f 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2969,9 +2969,11 @@
 	/*
 	 * in case stdin is USB and still active on IBM machines...
 	 * Unfortunately quiesce crashes on some powermacs if we have
-	 * closed stdin already (in particular the powerbook 101).
+	 * closed stdin already (in particular the powerbook 101). It
+	 * appears that the OPAL version of OFW doesn't like it either.
 	 */
-	if (RELOC(of_platform) != PLATFORM_POWERMAC)
+	if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+	    RELOC(of_platform) != PLATFORM_OPAL)
 		prom_close_stdin();
 
 	/*
@@ -2987,8 +2989,12 @@
 	 * is common to us and kexec
 	 */
 	hdr = RELOC(dt_header_start);
-	prom_printf("returning from prom_init\n");
-	prom_debug("->dt_header_start=0x%x\n", hdr);
+
+	/* Don't print anything after quiesce under OPAL, it crashes OFW */
+	if (RELOC(of_platform) != PLATFORM_OPAL) {
+		prom_printf("returning from prom_init\n");
+		prom_debug("->dt_header_start=0x%x\n", hdr);
+	}
 
 #ifdef CONFIG_PPC32
 	reloc_got2(-offset);
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 4a3f46d..3bb07e5 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -99,3 +99,11 @@
 OPAL_CALL(opal_pci_map_pe_dma_window,		OPAL_PCI_MAP_PE_DMA_WINDOW);
 OPAL_CALL(opal_pci_map_pe_dma_window_real,	OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
 OPAL_CALL(opal_pci_reset,			OPAL_PCI_RESET);
+OPAL_CALL(opal_pci_get_hub_diag_data,		OPAL_PCI_GET_HUB_DIAG_DATA);
+OPAL_CALL(opal_pci_get_phb_diag_data,		OPAL_PCI_GET_PHB_DIAG_DATA);
+OPAL_CALL(opal_pci_fence_phb,			OPAL_PCI_FENCE_PHB);
+OPAL_CALL(opal_pci_reinit,			OPAL_PCI_REINIT);
+OPAL_CALL(opal_pci_mask_pe_error,		OPAL_PCI_MASK_PE_ERROR);
+OPAL_CALL(opal_set_slot_led_status,		OPAL_SET_SLOT_LED_STATUS);
+OPAL_CALL(opal_get_epow_status,			OPAL_GET_EPOW_STATUS);
+OPAL_CALL(opal_set_system_attention_led,	OPAL_SET_SYSTEM_ATTENTION_LED);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index cf89f30..f31162c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -9,7 +9,7 @@
  * 2 of the License, or (at your option) any later version.
  */
 
-#define DEBUG
+#undef DEBUG
 
 #include <linux/kernel.h>
 #include <linux/pci.h>
@@ -467,14 +467,13 @@
 	struct pci_bus *cbus;
 	struct pci_dev *cdev;
 	unsigned int i;
-	u16 cmd;
 
-	/* Clear all device enables  */
-	list_for_each_entry(cdev, &bus->devices, bus_list) {
-		pci_read_config_word(cdev, PCI_COMMAND, &cmd);
-		cmd &= ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER);
-		pci_write_config_word(cdev, PCI_COMMAND, cmd);
-	}
+	/* We used to clear all device enables here. However it looks like
+	 * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
+	 * and shoot fatal errors to the PHB which in turns fences itself
+	 * and we can't recover from that ... yet. So for now, let's leave
+	 * the enables as-is and hope for the best.
+	 */
 
 	/* Check if bus resources fit in our IO or M32 range */
 	for (i = 0; bus->self && (i < 2); i++) {
@@ -618,7 +617,7 @@
 		struct pci_dn *pdn = pnv_ioda_get_pdn(parent);
 		if (pdn && pdn->pe_number != IODA_INVALID_PE) {
 			rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
-						pe->pe_number, 1);
+						pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
 			/* XXX What to do in case of error ? */
 		}
 		parent = parent->bus->self;
@@ -638,7 +637,7 @@
 			pe->mve_number = -1;
 		} else {
 			rc = opal_pci_set_mve_enable(phb->opal_id,
-						     pe->mve_number, 1);
+						     pe->mve_number, OPAL_ENABLE_MVE);
 			if (rc) {
 				pe_err(pe, "OPAL error %ld enabling MVE %d\n",
 				       rc, pe->mve_number);
@@ -1187,6 +1186,12 @@
 	phb->opal_id = phb_id;
 	phb->type = PNV_PHB_IODA1;
 
+	/* Detect specific models for error handling */
+	if (of_device_is_compatible(np, "ibm,p7ioc-pciex"))
+		phb->model = PNV_PHB_MODEL_P7IOC;
+	else
+		phb->model = PNV_PHB_MODEL_UNKNOWN;
+
 	/* We parse "ranges" now since we need to deduce the register base
 	 * from the IO base
 	 */
@@ -1294,9 +1299,9 @@
 	pci_add_flags(PCI_REASSIGN_ALL_RSRC);
 
 	/* Reset IODA tables to a clean state */
-	rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_RESET, OPAL_ASSERT_RESET);
+	rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
 	if (rc)
-		pr_warning("  OPAL Error %ld performing IODA reset !\n", rc);
+		pr_warning("  OPAL Error %ld performing IODA table reset !\n", rc);
 	opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
 }
 
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index 4c80f7c..2649677 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -137,6 +137,7 @@
 	phb->hose->private_data = phb;
 	phb->opal_id = phb_id;
 	phb->type = PNV_PHB_P5IOC2;
+	phb->model = PNV_PHB_MODEL_P5IOC2;
 
 	phb->regs = of_iomap(np, 0);
 
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index c0ed379..a70bc1e 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -144,6 +144,112 @@
 }
 #endif /* CONFIG_PCI_MSI */
 
+static void pnv_pci_dump_p7ioc_diag_data(struct pnv_phb *phb)
+{
+	struct OpalIoP7IOCPhbErrorData *data = &phb->diag.p7ioc;
+	int i;
+
+	pr_info("PHB %d diagnostic data:\n", phb->hose->global_number);
+
+	pr_info("  brdgCtl              = 0x%08x\n", data->brdgCtl);
+
+	pr_info("  portStatusReg        = 0x%08x\n", data->portStatusReg);
+	pr_info("  rootCmplxStatus      = 0x%08x\n", data->rootCmplxStatus);
+	pr_info("  busAgentStatus       = 0x%08x\n", data->busAgentStatus);
+
+	pr_info("  deviceStatus         = 0x%08x\n", data->deviceStatus);
+	pr_info("  slotStatus           = 0x%08x\n", data->slotStatus);
+	pr_info("  linkStatus           = 0x%08x\n", data->linkStatus);
+	pr_info("  devCmdStatus         = 0x%08x\n", data->devCmdStatus);
+	pr_info("  devSecStatus         = 0x%08x\n", data->devSecStatus);
+
+	pr_info("  rootErrorStatus      = 0x%08x\n", data->rootErrorStatus);
+	pr_info("  uncorrErrorStatus    = 0x%08x\n", data->uncorrErrorStatus);
+	pr_info("  corrErrorStatus      = 0x%08x\n", data->corrErrorStatus);
+	pr_info("  tlpHdr1              = 0x%08x\n", data->tlpHdr1);
+	pr_info("  tlpHdr2              = 0x%08x\n", data->tlpHdr2);
+	pr_info("  tlpHdr3              = 0x%08x\n", data->tlpHdr3);
+	pr_info("  tlpHdr4              = 0x%08x\n", data->tlpHdr4);
+	pr_info("  sourceId             = 0x%08x\n", data->sourceId);
+
+	pr_info("  errorClass           = 0x%016llx\n", data->errorClass);
+	pr_info("  correlator           = 0x%016llx\n", data->correlator);
+
+	pr_info("  p7iocPlssr           = 0x%016llx\n", data->p7iocPlssr);
+	pr_info("  p7iocCsr             = 0x%016llx\n", data->p7iocCsr);
+	pr_info("  lemFir               = 0x%016llx\n", data->lemFir);
+	pr_info("  lemErrorMask         = 0x%016llx\n", data->lemErrorMask);
+	pr_info("  lemWOF               = 0x%016llx\n", data->lemWOF);
+	pr_info("  phbErrorStatus       = 0x%016llx\n", data->phbErrorStatus);
+	pr_info("  phbFirstErrorStatus  = 0x%016llx\n", data->phbFirstErrorStatus);
+	pr_info("  phbErrorLog0         = 0x%016llx\n", data->phbErrorLog0);
+	pr_info("  phbErrorLog1         = 0x%016llx\n", data->phbErrorLog1);
+	pr_info("  mmioErrorStatus      = 0x%016llx\n", data->mmioErrorStatus);
+	pr_info("  mmioFirstErrorStatus = 0x%016llx\n", data->mmioFirstErrorStatus);
+	pr_info("  mmioErrorLog0        = 0x%016llx\n", data->mmioErrorLog0);
+	pr_info("  mmioErrorLog1        = 0x%016llx\n", data->mmioErrorLog1);
+	pr_info("  dma0ErrorStatus      = 0x%016llx\n", data->dma0ErrorStatus);
+	pr_info("  dma0FirstErrorStatus = 0x%016llx\n", data->dma0FirstErrorStatus);
+	pr_info("  dma0ErrorLog0        = 0x%016llx\n", data->dma0ErrorLog0);
+	pr_info("  dma0ErrorLog1        = 0x%016llx\n", data->dma0ErrorLog1);
+	pr_info("  dma1ErrorStatus      = 0x%016llx\n", data->dma1ErrorStatus);
+	pr_info("  dma1FirstErrorStatus = 0x%016llx\n", data->dma1FirstErrorStatus);
+	pr_info("  dma1ErrorLog0        = 0x%016llx\n", data->dma1ErrorLog0);
+	pr_info("  dma1ErrorLog1        = 0x%016llx\n", data->dma1ErrorLog1);
+
+	for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
+		if ((data->pestA[i] >> 63) == 0 &&
+		    (data->pestB[i] >> 63) == 0)
+			continue;
+		pr_info("  PE[%3d] PESTA        = 0x%016llx\n", i, data->pestA[i]);
+		pr_info("          PESTB        = 0x%016llx\n", data->pestB[i]);
+	}
+}
+
+static void pnv_pci_dump_phb_diag_data(struct pnv_phb *phb)
+{
+	switch(phb->model) {
+	case PNV_PHB_MODEL_P7IOC:
+		pnv_pci_dump_p7ioc_diag_data(phb);
+		break;
+	default:
+		pr_warning("PCI %d: Can't decode this PHB diag data\n",
+			   phb->hose->global_number);
+	}
+}
+
+static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
+{
+	unsigned long flags, rc;
+	int has_diag;
+
+	spin_lock_irqsave(&phb->lock, flags);
+
+	rc = opal_pci_get_phb_diag_data(phb->opal_id, phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
+	has_diag = (rc == OPAL_SUCCESS);
+
+	rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+				       OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+	if (rc) {
+		pr_warning("PCI %d: Failed to clear EEH freeze state"
+			   " for PE#%d, err %ld\n",
+			   phb->hose->global_number, pe_no, rc);
+
+		/* For now, let's only display the diag buffer when we fail to clear
+		 * the EEH status. We'll do more sensible things later when we have
+		 * proper EEH support. We need to make sure we don't pollute ourselves
+		 * with the normal errors generated when probing empty slots
+		 */
+		if (has_diag)
+			pnv_pci_dump_phb_diag_data(phb);
+		else
+			pr_warning("PCI %d: No diag data available\n",
+				   phb->hose->global_number);
+	}
+
+	spin_unlock_irqrestore(&phb->lock, flags);
+}
+
 static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
 				     u32 bdfn)
 {
@@ -165,15 +271,8 @@
 	}
 	cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
 		bdfn, pe_no, fstate);
-	if (fstate != 0) {
-		rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
-					      OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
-		if (rc) {
-			pr_warning("PCI %d: Failed to clear EEH freeze state"
-				   " for PE#%d, err %lld\n",
-				   phb->hose->global_number, pe_no, rc);
-		}
-	}
+	if (fstate != 0)
+		pnv_pci_handle_eeh_config(phb, pe_no);
 }
 
 static int pnv_pci_read_config(struct pci_bus *bus,
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 28ae4ca..8bc4796 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -9,6 +9,15 @@
 	PNV_PHB_IODA2,
 };
 
+/* Precise PHB model for error management */
+enum pnv_phb_model {
+	PNV_PHB_MODEL_UNKNOWN,
+	PNV_PHB_MODEL_P5IOC2,
+	PNV_PHB_MODEL_P7IOC,
+};
+
+#define PNV_PCI_DIAG_BUF_SIZE	4096
+
 /* Data associated with a PE, including IOMMU tracking etc.. */
 struct pnv_ioda_pe {
 	/* A PE can be associated with a single device or an
@@ -56,6 +65,7 @@
 struct pnv_phb {
 	struct pci_controller	*hose;
 	enum pnv_phb_type	type;
+	enum pnv_phb_model	model;
 	u64			opal_id;
 	void __iomem		*regs;
 	spinlock_t		lock;
@@ -118,6 +128,12 @@
 			struct list_head	pe_list;
 		} ioda;
 	};
+
+	/* PHB status structure */
+	union {
+		unsigned char			blob[PNV_PCI_DIAG_BUF_SIZE];
+		struct OpalIoP7IOCPhbErrorData	p7ioc;
+	} diag;
 };
 
 extern struct pci_ops pnv_pci_ops;