summary refs log tree commit diff
path: root/arch/ppc64/kernel/eeh.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc64/kernel/eeh.c')
-rw-r--r--arch/ppc64/kernel/eeh.c55
1 files changed, 32 insertions, 23 deletions
diff --git a/arch/ppc64/kernel/eeh.c b/arch/ppc64/kernel/eeh.c
index 4c857a6516fc..ba93fd731222 100644
--- a/arch/ppc64/kernel/eeh.c
+++ b/arch/ppc64/kernel/eeh.c
@@ -254,6 +254,7 @@ pci_addr_cache_insert(struct pci_dev *dev, unsigned long alo,
 static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 {
 	struct device_node *dn;
+	struct pci_dn *pdn;
 	int i;
 	int inserted = 0;
 
@@ -265,8 +266,9 @@ static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 	}
 
 	/* Skip any devices for which EEH is not enabled. */
-	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
-	    dn->eeh_mode & EEH_MODE_NOCHECK) {
+	pdn = dn->data;
+	if (!(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
 #ifdef DEBUG
 		printk(KERN_INFO "PCI: skip building address cache for=%s\n",
 		       pci_name(dev));
@@ -415,6 +417,7 @@ int eeh_unregister_notifier(struct notifier_block *nb)
 static int read_slot_reset_state(struct device_node *dn, int rets[])
 {
 	int token, outputs;
+	struct pci_dn *pdn = dn->data;
 
 	if (ibm_read_slot_reset_state2 != RTAS_UNKNOWN_SERVICE) {
 		token = ibm_read_slot_reset_state2;
@@ -424,8 +427,8 @@ static int read_slot_reset_state(struct device_node *dn, int rets[])
 		outputs = 3;
 	}
 
-	return rtas_call(token, 3, outputs, rets, dn->eeh_config_addr,
-			 BUID_HI(dn->phb->buid), BUID_LO(dn->phb->buid));
+	return rtas_call(token, 3, outputs, rets, pdn->eeh_config_addr,
+			 BUID_HI(pdn->phb->buid), BUID_LO(pdn->phb->buid));
 }
 
 /**
@@ -534,6 +537,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	unsigned long flags;
 	int rc, reset_state;
 	struct eeh_event  *event;
+	struct pci_dn *pdn;
 
 	__get_cpu_var(total_mmio_ffs)++;
 
@@ -542,14 +546,15 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 
 	if (!dn)
 		return 0;
+	pdn = dn->data;
 
 	/* Access to IO BARs might get this far and still not want checking. */
-	if (!(dn->eeh_mode & EEH_MODE_SUPPORTED) ||
-	    dn->eeh_mode & EEH_MODE_NOCHECK) {
+	if (!pdn->eeh_capable || !(pdn->eeh_mode & EEH_MODE_SUPPORTED) ||
+	    pdn->eeh_mode & EEH_MODE_NOCHECK) {
 		return 0;
 	}
 
-	if (!dn->eeh_config_addr) {
+	if (!pdn->eeh_config_addr) {
 		return 0;
 	}
 
@@ -557,7 +562,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	 * If we already have a pending isolation event for this
 	 * slot, we know it's bad already, we don't need to check...
 	 */
-	if (dn->eeh_mode & EEH_MODE_ISOLATED) {
+	if (pdn->eeh_mode & EEH_MODE_ISOLATED) {
 		atomic_inc(&eeh_fail_count);
 		if (atomic_read(&eeh_fail_count) >= EEH_MAX_FAILS) {
 			/* re-read the slot reset state */
@@ -582,7 +587,7 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	}
 
 	/* prevent repeated reports of this failure */
-	dn->eeh_mode |= EEH_MODE_ISOLATED;
+	pdn->eeh_mode |= EEH_MODE_ISOLATED;
 
 	reset_state = rets[0];
 
@@ -590,9 +595,9 @@ int eeh_dn_check_failure(struct device_node *dn, struct pci_dev *dev)
 	memset(slot_errbuf, 0, eeh_error_buf_size);
 
 	rc = rtas_call(ibm_slot_error_detail,
-	               8, 1, NULL, dn->eeh_config_addr,
-	               BUID_HI(dn->phb->buid),
-	               BUID_LO(dn->phb->buid), NULL, 0,
+	               8, 1, NULL, pdn->eeh_config_addr,
+	               BUID_HI(pdn->phb->buid),
+	               BUID_LO(pdn->phb->buid), NULL, 0,
 	               virt_to_phys(slot_errbuf),
 	               eeh_error_buf_size,
 	               1 /* Temporary Error */);
@@ -679,8 +684,9 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
 	u32 *device_id = (u32 *)get_property(dn, "device-id", NULL);
 	u32 *regs;
 	int enable;
+	struct pci_dn *pdn = dn->data;
 
-	dn->eeh_mode = 0;
+	pdn->eeh_mode = 0;
 
 	if (status && strcmp(status, "ok") != 0)
 		return NULL;	/* ignore devices with bad status */
@@ -691,7 +697,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
 
 	/* There is nothing to check on PCI to ISA bridges */
 	if (dn->type && !strcmp(dn->type, "isa")) {
-		dn->eeh_mode |= EEH_MODE_NOCHECK;
+		pdn->eeh_mode |= EEH_MODE_NOCHECK;
 		return NULL;
 	}
 
@@ -708,7 +714,7 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
 		enable = 0;
 
 	if (!enable)
-		dn->eeh_mode |= EEH_MODE_NOCHECK;
+		pdn->eeh_mode |= EEH_MODE_NOCHECK;
 
 	/* Ok... see if this device supports EEH.  Some do, some don't,
 	 * and the only way to find out is to check each and every one. */
@@ -721,8 +727,8 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
 				EEH_ENABLE);
 		if (ret == 0) {
 			eeh_subsystem_enabled = 1;
-			dn->eeh_mode |= EEH_MODE_SUPPORTED;
-			dn->eeh_config_addr = regs[0];
+			pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+			pdn->eeh_config_addr = regs[0];
 #ifdef DEBUG
 			printk(KERN_DEBUG "EEH: %s: eeh enabled\n", dn->full_name);
 #endif
@@ -730,10 +736,11 @@ static void *early_enable_eeh(struct device_node *dn, void *data)
 
 			/* This device doesn't support EEH, but it may have an
 			 * EEH parent, in which case we mark it as supported. */
-			if (dn->parent && (dn->parent->eeh_mode & EEH_MODE_SUPPORTED)) {
+			if (dn->parent && dn->parent->data
+			    && (PCI_DN(dn->parent)->eeh_mode & EEH_MODE_SUPPORTED)) {
 				/* Parent supports EEH. */
-				dn->eeh_mode |= EEH_MODE_SUPPORTED;
-				dn->eeh_config_addr = dn->parent->eeh_config_addr;
+				pdn->eeh_mode |= EEH_MODE_SUPPORTED;
+				pdn->eeh_config_addr = PCI_DN(dn->parent)->eeh_config_addr;
 				return NULL;
 			}
 		}
@@ -790,11 +797,13 @@ void __init eeh_init(void)
 	for (phb = of_find_node_by_name(NULL, "pci"); phb;
 	     phb = of_find_node_by_name(phb, "pci")) {
 		unsigned long buid;
+		struct pci_dn *pci;
 
 		buid = get_phb_buid(phb);
-		if (buid == 0)
+		if (buid == 0 || phb->data == NULL)
 			continue;
 
+		pci = phb->data;
 		info.buid_lo = BUID_LO(buid);
 		info.buid_hi = BUID_HI(buid);
 		traverse_pci_devices(phb, early_enable_eeh, &info);
@@ -823,9 +832,9 @@ void eeh_add_device_early(struct device_node *dn)
 	struct pci_controller *phb;
 	struct eeh_early_enable_info info;
 
-	if (!dn)
+	if (!dn || !dn->data)
 		return;
-	phb = dn->phb;
+	phb = PCI_DN(dn)->phb;
 	if (NULL == phb || 0 == phb->buid) {
 		printk(KERN_WARNING "EEH: Expected buid but found none\n");
 		return;