[PATCH] Separate pci bits out of struct device_node

Paul Mackerras paulus at samba.org
Tue Sep 6 13:17:54 EST 2005


This patch pulls the PCI-related junk out of struct device_node and
puts it in a separate structure, struct pci_dn.  The device_node now
just has a void * pointer in it, which points to a struct pci_dn for
nodes that represent PCI devices.  It could potentially be used in
future for device-specific data for other sorts of devices, such as
virtual I/O devices.

Signed-off-by: Paul Mackerras <paulus at samba.org>
---
diff -urN linux-2.6/arch/ppc64/kernel/eeh.c pcidn/arch/ppc64/kernel/eeh.c
--- linux-2.6/arch/ppc64/kernel/eeh.c	2005-06-24 13:38:52.000000000 +1000
+++ pcidn/arch/ppc64/kernel/eeh.c	2005-09-06 09:53:00.000000000 +1000
@@ -255,6 +255,7 @@
 static void __pci_addr_cache_insert_device(struct pci_dev *dev)
 {
 	struct device_node *dn;
+	struct pci_dn *pdn;
 	int i;
 	int inserted = 0;
 
@@ -266,8 +267,9 @@
 	}
 
 	/* 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 %s\n",
 		       pci_name(dev), pci_pretty_name(dev));
@@ -416,6 +418,7 @@
 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;
@@ -425,8 +428,8 @@
 		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));
 }
 
 /**
@@ -535,6 +538,7 @@
 	unsigned long flags;
 	int rc, reset_state;
 	struct eeh_event  *event;
+	struct pci_dn *pdn;
 
 	__get_cpu_var(total_mmio_ffs)++;
 
@@ -543,14 +547,15 @@
 
 	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;
 	}
 
@@ -558,7 +563,7 @@
 	 * 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 */
@@ -583,7 +588,7 @@
 	}
 
 	/* prevent repeated reports of this failure */
-	dn->eeh_mode |= EEH_MODE_ISOLATED;
+	pdn->eeh_mode |= EEH_MODE_ISOLATED;
 
 	reset_state = rets[0];
 
@@ -591,9 +596,9 @@
 	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 */);
@@ -680,8 +685,9 @@
 	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 */
@@ -692,7 +698,7 @@
 
 	/* 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;
 	}
 
@@ -709,7 +715,7 @@
 		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. */
@@ -722,8 +728,8 @@
 				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
@@ -731,10 +737,11 @@
 
 			/* 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;
 			}
 		}
@@ -791,11 +798,13 @@
 	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);
@@ -824,9 +833,9 @@
 	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;
diff -urN linux-2.6/arch/ppc64/kernel/iommu.c pcidn/arch/ppc64/kernel/iommu.c
--- linux-2.6/arch/ppc64/kernel/iommu.c	2005-08-18 12:59:18.000000000 +1000
+++ pcidn/arch/ppc64/kernel/iommu.c	2005-09-06 08:18:54.000000000 +1000
@@ -438,7 +438,8 @@
 
 void iommu_free_table(struct device_node *dn)
 {
-	struct iommu_table *tbl = dn->iommu_table;
+	struct pci_dn *pdn = dn->data;
+	struct iommu_table *tbl = pdn->iommu_table;
 	unsigned long bitmap_sz, i;
 	unsigned int order;
 
diff -urN linux-2.6/arch/ppc64/kernel/maple_pci.c pcidn/arch/ppc64/kernel/maple_pci.c
--- linux-2.6/arch/ppc64/kernel/maple_pci.c	2005-04-26 15:37:55.000000000 +1000
+++ pcidn/arch/ppc64/kernel/maple_pci.c	2005-09-06 10:13:13.000000000 +1000
@@ -447,9 +447,9 @@
 	 */
 	if (u3_agp) {
 		struct device_node *np = u3_agp->arch_data;
-		np->busno = 0xf0;
+		PCI_DN(np)->busno = 0xf0;
 		for (np = np->child; np; np = np->sibling)
-			np->busno = 0xf0;
+			PCI_DN(np)->busno = 0xf0;
 	}
 
 	/* Tell pci.c to use the common resource allocation mecanism */
diff -urN linux-2.6/arch/ppc64/kernel/pSeries_iommu.c pcidn/arch/ppc64/kernel/pSeries_iommu.c
--- linux-2.6/arch/ppc64/kernel/pSeries_iommu.c	2005-08-30 11:43:32.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pSeries_iommu.c	2005-09-06 09:51:49.000000000 +1000
@@ -295,7 +295,7 @@
 				      struct iommu_table *tbl,
 				      unsigned int *dma_window)
 {
-	tbl->it_busno  = dn->bussubno;
+	tbl->it_busno  = PCI_DN(dn)->bussubno;
 
 	/* TODO: Parse field size properties properly. */
 	tbl->it_size   = (((unsigned long)dma_window[4] << 32) |
@@ -311,6 +311,7 @@
 static void iommu_bus_setup_pSeries(struct pci_bus *bus)
 {
 	struct device_node *dn, *pdn;
+	struct pci_dn *pci;
 	struct iommu_table *tbl;
 
 	DBG("iommu_bus_setup_pSeries, bus %p, bus->self %p\n", bus, bus->self);
@@ -325,6 +326,7 @@
 	 */
 
 	dn = pci_bus_to_OF_node(bus);
+	pci = dn->data;
 
 	if (!bus->self) {
 		/* Root bus */
@@ -341,18 +343,18 @@
 				 * alltogether. This leaves 768MB for the window.
 				 */
 				DBG("PHB has io-hole, reserving 256MB\n");
-				dn->phb->dma_window_size = 3 << 28;
-				dn->phb->dma_window_base_cur = 1 << 28;
+				pci->phb->dma_window_size = 3 << 28;
+				pci->phb->dma_window_base_cur = 1 << 28;
 			} else {
 				/* 1GB window by default */
-				dn->phb->dma_window_size = 1 << 30;
-				dn->phb->dma_window_base_cur = 0;
+				pci->phb->dma_window_size = 1 << 30;
+				pci->phb->dma_window_base_cur = 0;
 			}
 
 			tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-			iommu_table_setparms(dn->phb, dn, tbl);
-			dn->iommu_table = iommu_init_table(tbl);
+			iommu_table_setparms(pci->phb, dn, tbl);
+			pci->iommu_table = iommu_init_table(tbl);
 		} else {
 			/* Do a 128MB table at root. This is used for the IDE
 			 * controller on some SMP-mode POWER4 machines. It
@@ -363,16 +365,16 @@
 			 * Allocate at offset 128MB to avoid having to deal
 			 * with ISA holes; 128MB table for IDE is plenty.
 			 */
-			dn->phb->dma_window_size = 1 << 27;
-			dn->phb->dma_window_base_cur = 1 << 27;
+			pci->phb->dma_window_size = 1 << 27;
+			pci->phb->dma_window_base_cur = 1 << 27;
 
 			tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-			iommu_table_setparms(dn->phb, dn, tbl);
-			dn->iommu_table = iommu_init_table(tbl);
+			iommu_table_setparms(pci->phb, dn, tbl);
+			pci->iommu_table = iommu_init_table(tbl);
 
 			/* All child buses have 256MB tables */
-			dn->phb->dma_window_size = 1 << 28;
+			pci->phb->dma_window_size = 1 << 28;
 		}
 	} else {
 		pdn = pci_bus_to_OF_node(bus->parent);
@@ -386,12 +388,12 @@
 
 			tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-			iommu_table_setparms(dn->phb, dn, tbl);
+			iommu_table_setparms(pci->phb, dn, tbl);
 
-			dn->iommu_table = iommu_init_table(tbl);
+			pci->iommu_table = iommu_init_table(tbl);
 		} else {
 			/* Lower than first child or under python, use parent table */
-			dn->iommu_table = pdn->iommu_table;
+			pci->iommu_table = PCI_DN(pdn)->iommu_table;
 		}
 	}
 }
@@ -401,6 +403,7 @@
 {
 	struct iommu_table *tbl;
 	struct device_node *dn, *pdn;
+	struct pci_dn *ppci;
 	unsigned int *dma_window = NULL;
 
 	DBG("iommu_bus_setup_pSeriesLP, bus %p, bus->self %p\n", bus, bus->self);
@@ -419,22 +422,24 @@
 		return;
 	}
 
-	if (!pdn->iommu_table) {
+	ppci = pdn->data;
+	if (!ppci->iommu_table) {
 		/* Bussubno hasn't been copied yet.
 		 * Do it now because iommu_table_setparms_lpar needs it.
 		 */
-		pdn->bussubno = bus->number;
+
+		ppci->bussubno = bus->number;
 
 		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
 						    GFP_KERNEL);
 	
-		iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+		iommu_table_setparms_lpar(ppci->phb, pdn, tbl, dma_window);
 
-		pdn->iommu_table = iommu_init_table(tbl);
+		ppci->iommu_table = iommu_init_table(tbl);
 	}
 
 	if (pdn != dn)
-		dn->iommu_table = pdn->iommu_table;
+		PCI_DN(dn)->iommu_table = ppci->iommu_table;
 }
 
 
@@ -449,11 +454,11 @@
 	 */
 	mydn = dn = pci_device_to_OF_node(dev);
 
-	while (dn && dn->iommu_table == NULL)
+	while (dn && dn->data && PCI_DN(dn)->iommu_table == NULL)
 		dn = dn->parent;
 
-	if (dn) {
-		mydn->iommu_table = dn->iommu_table;
+	if (dn && dn->data) {
+		PCI_DN(mydn)->iommu_table = PCI_DN(dn)->iommu_table;
 	} else {
 		DBG("iommu_dev_setup_pSeries, dev %p (%s) has no iommu table\n", dev, dev->pretty_name);
 	}
@@ -463,10 +468,11 @@
 {
 	int err = NOTIFY_OK;
 	struct device_node *np = node;
+	struct pci_dn *pci = np->data;
 
 	switch (action) {
 	case PSERIES_RECONFIG_REMOVE:
-		if (np->iommu_table &&
+		if (pci->iommu_table &&
 		    get_property(np, "ibm,dma-window", NULL))
 			iommu_free_table(np);
 		break;
@@ -486,6 +492,7 @@
 	struct device_node *pdn, *dn;
 	struct iommu_table *tbl;
 	int *dma_window = NULL;
+	struct pci_dn *pci;
 
 	DBG("iommu_dev_setup_pSeriesLP, dev %p (%s)\n", dev, dev->pretty_name);
 
@@ -497,8 +504,10 @@
 	 */
 	dn = pci_device_to_OF_node(dev);
 
-	for (pdn = dn; pdn && !pdn->iommu_table; pdn = pdn->parent) {
-		dma_window = (unsigned int *)get_property(pdn, "ibm,dma-window", NULL);
+	for (pdn = dn; pdn && pdn->data && !PCI_DN(pdn)->iommu_table;
+	     pdn = pdn->parent) {
+		dma_window = (unsigned int *)
+			get_property(pdn, "ibm,dma-window", NULL);
 		if (dma_window)
 			break;
 	}
@@ -515,20 +524,21 @@
 		DBG("Found DMA window, allocating table\n");
 	}
 
-	if (!pdn->iommu_table) {
+	pci = pdn->data;
+	if (!pci->iommu_table) {
 		/* iommu_table_setparms_lpar needs bussubno. */
-		pdn->bussubno = pdn->phb->bus->number;
+		pci->bussubno = pci->phb->bus->number;
 
 		tbl = (struct iommu_table *)kmalloc(sizeof(struct iommu_table),
 						    GFP_KERNEL);
 
-		iommu_table_setparms_lpar(pdn->phb, pdn, tbl, dma_window);
+		iommu_table_setparms_lpar(pci->phb, pdn, tbl, dma_window);
 
-		pdn->iommu_table = iommu_init_table(tbl);
+		pci->iommu_table = iommu_init_table(tbl);
 	}
 
 	if (pdn != dn)
-		dn->iommu_table = pdn->iommu_table;
+		PCI_DN(dn)->iommu_table = pci->iommu_table;
 }
 
 static void iommu_bus_setup_null(struct pci_bus *b) { }
diff -urN linux-2.6/arch/ppc64/kernel/pci.c pcidn/arch/ppc64/kernel/pci.c
--- linux-2.6/arch/ppc64/kernel/pci.c	2005-08-05 16:04:58.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pci.c	2005-09-06 09:25:07.000000000 +1000
@@ -838,9 +838,11 @@
         * device tree.  If they are then we need to scan all the
         * functions of this slot.
         */
-       for (dn = busdn->child; dn; dn = dn->sibling)
-               if ((dn->devfn >> 3) == (devfn >> 3))
+       for (dn = busdn->child; dn; dn = dn->sibling) {
+	       struct pci_dn *pdn = dn->data;
+	       if (pdn && (pdn->devfn >> 3) == (devfn >> 3))
                        return 1;
+       }
 
        return 0;
 }
diff -urN linux-2.6/arch/ppc64/kernel/pci.h pcidn/arch/ppc64/kernel/pci.h
--- linux-2.6/arch/ppc64/kernel/pci.h	2005-06-24 13:38:52.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pci.h	2005-09-06 08:18:54.000000000 +1000
@@ -34,7 +34,6 @@
 
 void pci_devs_phb_init(void);
 void pci_devs_phb_init_dynamic(struct pci_controller *phb);
-struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
 /* PCI address cache management routines */
 void pci_addr_cache_insert_device(struct pci_dev *dev);
diff -urN linux-2.6/arch/ppc64/kernel/pci_dn.c pcidn/arch/ppc64/kernel/pci_dn.c
--- linux-2.6/arch/ppc64/kernel/pci_dn.c	2005-04-26 15:37:55.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pci_dn.c	2005-09-06 11:39:47.000000000 +1000
@@ -23,6 +23,8 @@
 #include <linux/pci.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/bootmem.h>
 
 #include <asm/io.h>
 #include <asm/prom.h>
@@ -40,16 +42,26 @@
 	struct pci_controller *phb = data;
 	int *type = (int *)get_property(dn, "ibm,pci-config-space-type", NULL);
 	u32 *regs;
+	struct pci_dn *pdn;
 
-	dn->phb = phb;
+	if (phb->is_dynamic)
+		pdn = kmalloc(sizeof(*pdn), GFP_KERNEL);
+	else
+		pdn = alloc_bootmem(sizeof(*pdn));
+	if (pdn == NULL)
+		return NULL;
+	memset(pdn, 0, sizeof(*pdn));
+	dn->data = pdn;
+	pdn->node = dn;
+	pdn->phb = phb;
 	regs = (u32 *)get_property(dn, "reg", NULL);
 	if (regs) {
 		/* First register entry is addr (00BBSS00)  */
-		dn->busno = (regs[0] >> 16) & 0xff;
-		dn->devfn = (regs[0] >> 8) & 0xff;
+		pdn->busno = (regs[0] >> 16) & 0xff;
+		pdn->devfn = (regs[0] >> 8) & 0xff;
 	}
 
-	dn->pci_ext_config_space = (type && *type == 1);
+	pdn->pci_ext_config_space = (type && *type == 1);
 	return NULL;
 }
 
@@ -112,10 +124,15 @@
 void __devinit pci_devs_phb_init_dynamic(struct pci_controller *phb)
 {
 	struct device_node * dn = (struct device_node *) phb->arch_data;
+	struct pci_dn *pdn;
 
 	/* PHB nodes themselves must not match */
-	dn->devfn = dn->busno = -1;
-	dn->phb = phb;
+	update_dn_pci_info(dn, phb);
+	pdn = dn->data;
+	if (pdn) {
+		pdn->devfn = pdn->busno = -1;
+		pdn->phb = phb;
+	}
 
 	/* Update dn->phb ptrs for new phb and children devices */
 	traverse_pci_devices(dn, update_dn_pci_info, phb);
@@ -123,14 +140,17 @@
 
 /*
  * Traversal func that looks for a <busno,devfcn> value.
- * If found, the device_node is returned (thus terminating the traversal).
+ * If found, the pci_dn is returned (thus terminating the traversal).
  */
 static void *is_devfn_node(struct device_node *dn, void *data)
 {
 	int busno = ((unsigned long)data >> 8) & 0xff;
 	int devfn = ((unsigned long)data) & 0xff;
+	struct pci_dn *pci = dn->data;
 
-	return ((devfn == dn->devfn) && (busno == dn->busno)) ? dn : NULL;
+	if (pci && (devfn == pci->devfn) && (busno == pci->busno))
+		return dn;
+	return NULL;
 }
 
 /*
@@ -149,13 +169,10 @@
 struct device_node *fetch_dev_dn(struct pci_dev *dev)
 {
 	struct device_node *orig_dn = dev->sysdata;
-	struct pci_controller *phb = orig_dn->phb; /* assume same phb as orig_dn */
-	struct device_node *phb_dn;
 	struct device_node *dn;
 	unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
 
-	phb_dn = phb->arch_data;
-	dn = traverse_pci_devices(phb_dn, is_devfn_node, (void *)searchval);
+	dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
 	if (dn)
 		dev->sysdata = dn;
 	return dn;
@@ -165,11 +182,13 @@
 static int pci_dn_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
 {
 	struct device_node *np = node;
+	struct pci_dn *pci;
 	int err = NOTIFY_OK;
 
 	switch (action) {
 	case PSERIES_RECONFIG_ADD:
-		update_dn_pci_info(np, np->parent->phb);
+		pci = np->parent->data;
+		update_dn_pci_info(np, pci->phb);
 		break;
 	default:
 		err = NOTIFY_DONE;
diff -urN linux-2.6/arch/ppc64/kernel/pci_iommu.c pcidn/arch/ppc64/kernel/pci_iommu.c
--- linux-2.6/arch/ppc64/kernel/pci_iommu.c	2005-04-26 15:37:55.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pci_iommu.c	2005-09-06 09:58:44.000000000 +1000
@@ -66,7 +66,7 @@
 #endif /* CONFIG_PPC_ISERIES */
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-	return PCI_GET_DN(pdev)->iommu_table;
+	return PCI_DN(PCI_GET_DN(pdev))->iommu_table;
 #endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
diff -urN linux-2.6/arch/ppc64/kernel/pmac_feature.c pcidn/arch/ppc64/kernel/pmac_feature.c
--- linux-2.6/arch/ppc64/kernel/pmac_feature.c	2005-04-26 15:37:55.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pmac_feature.c	2005-09-06 10:14:24.000000000 +1000
@@ -674,6 +674,7 @@
 #if 0 /* Disabled for now */
 	u32	ufreq, freq, ucfg, cfg;
 	struct device_node *pcix_node;
+	struct pci_dn *pdn;
 	u8  	px_bus, px_devfn;
 	struct pci_controller *px_hose;
 
@@ -687,9 +688,10 @@
 		printk("No PCI-X bridge found\n");
 		return;
 	}
-	px_hose = pcix_node->phb;
-	px_bus = pcix_node->busno;
-	px_devfn = pcix_node->devfn;
+	pdn = pcix_node->data;
+	px_hose = pdn->phb;
+	px_bus = pdn->busno;
+	px_devfn = pdn->devfn;
 	
 	early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg);
 	early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq);
diff -urN linux-2.6/arch/ppc64/kernel/pmac_pci.c pcidn/arch/ppc64/kernel/pmac_pci.c
--- linux-2.6/arch/ppc64/kernel/pmac_pci.c	2005-04-26 15:37:55.000000000 +1000
+++ pcidn/arch/ppc64/kernel/pmac_pci.c	2005-09-06 10:12:57.000000000 +1000
@@ -242,7 +242,7 @@
 	else
 		busdn = hose->arch_data;
 	for (dn = busdn->child; dn; dn = dn->sibling)
-		if (dn->devfn == devfn)
+		if (dn->data && PCI_DN(dn)->devfn == devfn)
 			break;
 	if (dn == NULL)
 		return -1;
@@ -746,9 +746,9 @@
 	 */
 	if (u3_agp) {
 		struct device_node *np = u3_agp->arch_data;
-		np->busno = 0xf0;
+		PCI_DN(np)->busno = 0xf0;
 		for (np = np->child; np; np = np->sibling)
-			np->busno = 0xf0;
+			PCI_DN(np)->busno = 0xf0;
 	}
 
 	pmac_check_ht_link();
diff -urN linux-2.6/arch/ppc64/kernel/rtas_pci.c pcidn/arch/ppc64/kernel/rtas_pci.c
--- linux-2.6/arch/ppc64/kernel/rtas_pci.c	2005-08-30 11:43:32.000000000 +1000
+++ pcidn/arch/ppc64/kernel/rtas_pci.c	2005-09-06 09:52:59.000000000 +1000
@@ -48,7 +48,7 @@
 static int ibm_read_pci_config;
 static int ibm_write_pci_config;
 
-static int config_access_valid(struct device_node *dn, int where)
+static int config_access_valid(struct pci_dn *dn, int where)
 {
 	if (where < 256)
 		return 1;
@@ -78,15 +78,17 @@
 	int returnval = -1;
 	unsigned long buid, addr;
 	int ret;
+	struct pci_dn *pdn;
 
-	if (!dn)
+	if (!dn || !dn->data)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (!config_access_valid(dn, where))
+	pdn = dn->data;
+	if (!config_access_valid(pdn, where))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-		(dn->devfn << 8) | (where & 0xff);
-	buid = dn->phb->buid;
+	addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+		(pdn->devfn << 8) | (where & 0xff);
+	buid = pdn->phb->buid;
 	if (buid) {
 		ret = rtas_call(ibm_read_pci_config, 4, 2, &returnval,
 				addr, buid >> 32, buid & 0xffffffff, size);
@@ -98,8 +100,8 @@
 	if (ret)
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
-	if (returnval == EEH_IO_ERROR_VALUE(size)
-	    && eeh_dn_check_failure (dn, NULL))
+	if (returnval == EEH_IO_ERROR_VALUE(size) &&
+	    eeh_dn_check_failure (dn, NULL))
 		return PCIBIOS_DEVICE_NOT_FOUND;
 
 	return PCIBIOS_SUCCESSFUL;
@@ -118,24 +120,28 @@
 
 	/* Search only direct children of the bus */
 	for (dn = busdn->child; dn; dn = dn->sibling)
-		if (dn->devfn == devfn && of_device_available(dn))
+		if (dn->data && PCI_DN(dn)->devfn == devfn
+		    && of_device_available(dn))
 			return rtas_read_config(dn, where, size, val);
+
 	return PCIBIOS_DEVICE_NOT_FOUND;
 }
 
-static int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
+int rtas_write_config(struct device_node *dn, int where, int size, u32 val)
 {
 	unsigned long buid, addr;
 	int ret;
+	struct pci_dn *pdn;
 
-	if (!dn)
+	if (!dn || !dn->data)
 		return PCIBIOS_DEVICE_NOT_FOUND;
-	if (!config_access_valid(dn, where))
+	pdn = dn->data;
+	if (!config_access_valid(pdn, where))
 		return PCIBIOS_BAD_REGISTER_NUMBER;
 
-	addr = ((where & 0xf00) << 20) | (dn->busno << 16) |
-		(dn->devfn << 8) | (where & 0xff);
-	buid = dn->phb->buid;
+	addr = ((where & 0xf00) << 20) | (pdn->busno << 16) |
+		(pdn->devfn << 8) | (where & 0xff);
+	buid = pdn->phb->buid;
 	if (buid) {
 		ret = rtas_call(ibm_write_pci_config, 5, 1, NULL, addr, buid >> 32, buid & 0xffffffff, size, (ulong) val);
 	} else {
@@ -161,7 +167,8 @@
 
 	/* Search only direct children of the bus */
 	for (dn = busdn->child; dn; dn = dn->sibling)
-		if (dn->devfn == devfn && of_device_available(dn))
+		if (dn->data && PCI_DN(dn)->devfn == devfn
+		    && of_device_available(dn))
 			return rtas_write_config(dn, where, size, val);
 	return PCIBIOS_DEVICE_NOT_FOUND;
 }
diff -urN linux-2.6/arch/ppc64/kernel/sys_ppc32.c pcidn/arch/ppc64/kernel/sys_ppc32.c
--- linux-2.6/arch/ppc64/kernel/sys_ppc32.c	2005-07-14 20:07:04.000000000 +1000
+++ pcidn/arch/ppc64/kernel/sys_ppc32.c	2005-09-06 09:58:44.000000000 +1000
@@ -747,8 +747,8 @@
 	if (bus == NULL || bus->sysdata == NULL)
 		return -ENODEV;
 
-	hose_node = (struct device_node *)bus->sysdata;
-	hose = hose_node->phb;
+	hose_node = bus->sysdata;
+	hose = PCI_DN(hose_node)->phb;
 
 	switch (which) {
 	case IOBASE_BRIDGE_NUMBER:
diff -urN linux-2.6/arch/ppc64/kernel/u3_iommu.c pcidn/arch/ppc64/kernel/u3_iommu.c
--- linux-2.6/arch/ppc64/kernel/u3_iommu.c	2005-04-26 15:37:55.000000000 +1000
+++ pcidn/arch/ppc64/kernel/u3_iommu.c	2005-09-06 10:14:57.000000000 +1000
@@ -276,7 +276,7 @@
 	dn = pci_device_to_OF_node(dev);
 
 	if (dn)
-		dn->iommu_table = &iommu_table_u3;
+		PCI_DN(dn)->iommu_table = &iommu_table_u3;
 }
 
 static void iommu_bus_setup_u3(struct pci_bus *bus)
@@ -291,7 +291,7 @@
 	dn = pci_bus_to_OF_node(bus);
 
 	if (dn)
-		dn->iommu_table = &iommu_table_u3;
+		PCI_DN(dn)->iommu_table = &iommu_table_u3;
 }
 
 static void iommu_dev_setup_null(struct pci_dev *dev) { }
diff -urN linux-2.6/drivers/pci/hotplug/rpadlpar_core.c pcidn/drivers/pci/hotplug/rpadlpar_core.c
--- linux-2.6/drivers/pci/hotplug/rpadlpar_core.c	2005-04-26 15:37:58.000000000 +1000
+++ pcidn/drivers/pci/hotplug/rpadlpar_core.c	2005-09-06 08:18:54.000000000 +1000
@@ -131,7 +131,8 @@
 static int pci_add_secondary_bus(struct device_node *dn,
 		struct pci_dev *bridge_dev)
 {
-	struct pci_controller *hose = dn->phb;
+	struct pci_dn *pdn = dn->data;
+	struct pci_controller *hose = pdn->phb;
 	struct pci_bus *child;
 	u8 sec_busno;
 
@@ -156,7 +157,7 @@
 	if (hose->last_busno < child->number)
 		hose->last_busno = child->number;
 
-	dn->bussubno = child->number;
+	pdn->bussubno = child->number;
 
 	/* ioremap() for child bus, which may or may not succeed */
 	remap_bus_range(child);
@@ -166,11 +167,12 @@
 
 static struct pci_dev *dlpar_pci_add_bus(struct device_node *dn)
 {
-	struct pci_controller *hose = dn->phb;
+	struct pci_dn *pdn = dn->data;
+	struct pci_controller *hose = pdn->phb;
 	struct pci_dev *dev = NULL;
 
 	/* Scan phb bus for EADS device, adding new one to bus->devices */
-	if (!pci_scan_single_device(hose->bus, dn->devfn)) {
+	if (!pci_scan_single_device(hose->bus, pdn->devfn)) {
 		printk(KERN_ERR "%s: found no device on bus\n", __FUNCTION__);
 		return NULL;
 	}
@@ -259,16 +261,18 @@
 {
 	struct pci_controller *phb;
 	struct device_node *dn;
+	struct pci_dn *pdn;
 	int rc = 0;
 
 	dn = slot->dn;
-	if (!dn) {
+	if (!dn || !dn->data) {
 		printk(KERN_ERR "%s: unexpected NULL slot device node\n",
 				__FUNCTION__);
 		return -EIO;
 	}
 
-	phb = dn->phb;
+	pdn = dn->data;
+	phb = pdn->phb;
 	if (!phb) {
 		printk(KERN_ERR "%s: unexpected NULL phb pointer\n",
 				__FUNCTION__);
diff -urN linux-2.6/drivers/pci/hotplug/rpaphp_pci.c pcidn/drivers/pci/hotplug/rpaphp_pci.c
--- linux-2.6/drivers/pci/hotplug/rpaphp_pci.c	2005-04-26 15:37:58.000000000 +1000
+++ pcidn/drivers/pci/hotplug/rpaphp_pci.c	2005-09-06 08:18:54.000000000 +1000
@@ -33,10 +33,11 @@
 struct pci_dev *rpaphp_find_pci_dev(struct device_node *dn)
 {
 	struct pci_dev *dev = NULL;
+	struct pci_dn *pdn = dn->data;
 	char bus_id[BUS_ID_SIZE];
 
-	sprintf(bus_id, "%04x:%02x:%02x.%d", dn->phb->global_number,
-		dn->busno, PCI_SLOT(dn->devfn), PCI_FUNC(dn->devfn));
+	sprintf(bus_id, "%04x:%02x:%02x.%d", pdn->phb->global_number,
+		pdn->busno, PCI_SLOT(pdn->devfn), PCI_FUNC(pdn->devfn));
 	for_each_pci_dev(dev) {
 		if (!strcmp(pci_name(dev), bus_id)) {
 			break;
@@ -203,7 +204,8 @@
 
 	if (eads_first_child) {
 		/* pci_scan_slot should find all children of EADs */
-		num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(eads_first_child->devfn), 0));
+		struct pci_dn *pdn = eads_first_child->data;
+		num = pci_scan_slot(bus, PCI_DEVFN(PCI_SLOT(pdn->devfn), 0));
 		if (num) {
 			rpaphp_fixup_new_pci_devices(bus, 1); 
 			pci_bus_add_devices(bus);
@@ -359,14 +361,16 @@
 static int set_phb_slot_name(struct slot *slot)
 {
 	struct device_node *dn;
+	struct pci_dn *pdn;
 	struct pci_controller *phb;
 	struct pci_bus *bus;
 
 	dn = slot->dn;
-	if (!dn) {
+	if (!dn || !dn->data) {
 		return -EINVAL;
 	}
-	phb = dn->phb;
+	pdn = dn->data;
+	phb = pdn->phb;
 	if (!phb) {
 		return -EINVAL;
 	}
diff -urN linux-2.6/drivers/video/offb.c pcidn/drivers/video/offb.c
--- linux-2.6/drivers/video/offb.c	2005-04-26 15:37:59.000000000 +1000
+++ pcidn/drivers/video/offb.c	2005-09-06 08:18:54.000000000 +1000
@@ -363,7 +363,7 @@
 		address = (u_long) dp->addrs[i].address;
 
 #ifdef CONFIG_PPC64
-		address += dp->phb->pci_mem_offset;
+		address += ((struct pci_dn *)dp->data)->phb->pci_mem_offset;
 #endif
 
 		/* kludge for valkyrie */
diff -urN linux-2.6/include/asm-ppc64/pci-bridge.h pcidn/include/asm-ppc64/pci-bridge.h
--- linux-2.6/include/asm-ppc64/pci-bridge.h	2005-04-26 15:38:02.000000000 +1000
+++ pcidn/include/asm-ppc64/pci-bridge.h	2005-09-06 11:51:33.000000000 +1000
@@ -48,19 +48,52 @@
 	unsigned long dma_window_size;
 };
 
+/*
+ * PCI stuff, for nodes representing PCI devices, pointed to
+ * by device_node->data.
+ */
+struct pci_controller;
+struct iommu_table;
+
+struct pci_dn {
+	int	busno;			/* for pci devices */
+	int	bussubno;		/* for pci devices */
+	int	devfn;			/* for pci devices */
+	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
+	int	eeh_config_addr;
+	int	eeh_capable;		/* from firmware */
+	int 	eeh_check_count;	/* # times driver ignored error */
+	int 	eeh_freeze_count;	/* # times this device froze up. */
+	int	eeh_is_bridge;		/* device is pci-to-pci bridge */
+
+	int	pci_ext_config_space;	/* for pci devices */
+	struct  pci_controller *phb;	/* for pci devices */
+	struct	iommu_table *iommu_table;	/* for phb's or bridges */
+	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
+	struct	device_node *node;	/* back-pointer to the device_node */
+	u32	config_space[16];	/* saved PCI config space */
+};
+
+/* Get the pointer to a device_node's pci_dn */
+#define PCI_DN(dn)	((struct pci_dn *) (dn)->data)
+
 struct device_node *fetch_dev_dn(struct pci_dev *dev);
 
-/* Get a device_node from a pci_dev.  This code must be fast except in the case
- * where the sysdata is incorrect and needs to be fixed up (hopefully just once)
+/* Get a device_node from a pci_dev.  This code must be fast except
+ * in the case where the sysdata is incorrect and needs to be fixed
+ * up (this will only happen once).
+ * In this case the sysdata will have been inherited from a PCI host
+ * bridge or a PCI-PCI bridge further up the tree, so it will point
+ * to a valid struct pci_dn, just not the one we want.
  */
 static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
 {
 	struct device_node *dn = dev->sysdata;
+	struct pci_dn *pdn = dn->data;
 
-	if (dn->devfn == dev->devfn && dn->busno == dev->bus->number)
+	if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number)
 		return dn;	/* fast path.  sysdata is good */
-	else
-		return fetch_dev_dn(dev);
+	return fetch_dev_dn(dev);
 }
 
 static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
@@ -83,7 +116,7 @@
 	struct device_node *busdn = bus->sysdata;
 
 	BUG_ON(busdn == NULL);
-	return busdn->phb;
+	return PCI_DN(busdn)->phb;
 }
 
 #endif
diff -urN linux-2.6/include/asm-ppc64/prom.h pcidn/include/asm-ppc64/prom.h
--- linux-2.6/include/asm-ppc64/prom.h	2005-08-30 11:43:32.000000000 +1000
+++ pcidn/include/asm-ppc64/prom.h	2005-09-06 08:18:54.000000000 +1000
@@ -116,14 +116,6 @@
 	struct property *next;
 };
 
-/* NOTE: the device_node contains PCI specific info for pci devices.
- * This perhaps could be hung off the device_node with another struct,
- * but for now it is directly in the node.  The phb ptr is a good
- * indication of a real PCI node.  Other nodes leave these fields zeroed.
- */
-struct pci_controller;
-struct iommu_table;
-
 struct device_node {
 	char	*name;
 	char	*type;
@@ -135,16 +127,6 @@
 	struct	interrupt_info *intrs;
 	char	*full_name;
 
-	/* PCI stuff probably doesn't belong here */
-	int	busno;			/* for pci devices */
-	int	bussubno;		/* for pci devices */
-	int	devfn;			/* for pci devices */
-	int	eeh_mode;		/* See eeh.h for possible EEH_MODEs */
-	int	eeh_config_addr;
-	int	pci_ext_config_space;	/* for pci devices */
-	struct  pci_controller *phb;	/* for pci devices */
-	struct	iommu_table *iommu_table;	/* for phb's or bridges */
-
 	struct	property *properties;
 	struct	device_node *parent;
 	struct	device_node *child;
@@ -154,6 +136,7 @@
 	struct  proc_dir_entry *pde;	/* this node's proc directory */
 	struct  kref kref;
 	unsigned long _flags;
+	void	*data;
 };
 
 extern struct device_node *of_chosen;



More information about the Linuxppc64-dev mailing list