linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 01/14] powerpc: tidy up iseries/pci.c
@ 2006-05-19  6:42 Stephen Rothwell
  2006-05-19  6:43 ` [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32 Stephen Rothwell
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:42 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

Remove some unused counters.

No need to allocate iomm_table and iobar_table, which means that
iomm_table_initialize is not longer needed.

Use kzalloc where sensible.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/pci.c |   78 +++++-----------------------------
 1 files changed, 11 insertions(+), 67 deletions(-)

This series of patches are intenede to put the iSeries PCI devices into
the flattened device tree.  Built and run on an iSeries 270 with a single
PCI ethernet.  Built for pSeries_defconfig.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

039fac4f522c6207625993cd79bb2164dc0b91f1
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 428ffb5..91a9474 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -57,15 +57,6 @@ LIST_HEAD(iSeries_Global_Device_List);
 
 static int DeviceCount;
 
-/* Counters and control flags. */
-static long Pci_Io_Read_Count;
-static long Pci_Io_Write_Count;
-#if 0
-static long Pci_Cfg_Read_Count;
-static long Pci_Cfg_Write_Count;
-#endif
-static long Pci_Error_Count;
-
 static int Pci_Retry_Max = 3;	/* Only retry 3 times  */
 static int Pci_Error_Flag = 1;	/* Set Retry Error on. */
 
@@ -79,41 +70,19 @@ #define IOMM_TABLE_MAX_ENTRIES	1024
 #define IOMM_TABLE_ENTRY_SIZE	0x0000000000400000UL
 #define BASE_IO_MEMORY		0xE000000000000000UL
 
-static unsigned long max_io_memory = 0xE000000000000000UL;
+static unsigned long max_io_memory = BASE_IO_MEMORY;
 static long current_iomm_table_entry;
 
 /*
  * Lookup Tables.
  */
-static struct device_node **iomm_table;
-static u8 *iobar_table;
+static struct device_node *iomm_table[IOMM_TABLE_MAX_ENTRIES];
+static u8 iobar_table[IOMM_TABLE_MAX_ENTRIES];
 
-/*
- * Static and Global variables
- */
-static char *pci_io_text = "iSeries PCI I/O";
+static const char pci_io_text[] = "iSeries PCI I/O";
 static DEFINE_SPINLOCK(iomm_table_lock);
 
 /*
- * iomm_table_initialize
- *
- * Allocates and initalizes the Address Translation Table and Bar
- * Tables to get them ready for use.  Must be called before any
- * I/O space is handed out to the device BARs.
- */
-static void iomm_table_initialize(void)
-{
-	spin_lock(&iomm_table_lock);
-	iomm_table = kmalloc(sizeof(*iomm_table) * IOMM_TABLE_MAX_ENTRIES,
-			GFP_KERNEL);
-	iobar_table = kmalloc(sizeof(*iobar_table) * IOMM_TABLE_MAX_ENTRIES,
-			GFP_KERNEL);
-	spin_unlock(&iomm_table_lock);
-	if ((iomm_table == NULL) || (iobar_table == NULL))
-		panic("PCI: I/O tables allocation failed.\n");
-}
-
-/*
  * iomm_table_allocate_entry
  *
  * Adds pci_dev entry in address translation table
@@ -140,9 +109,8 @@ static void iomm_table_allocate_entry(st
 	 */
 	spin_lock(&iomm_table_lock);
 	bar_res->name = pci_io_text;
-	bar_res->start =
+	bar_res->start = BASE_IO_MEMORY +
 		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
-	bar_res->start += BASE_IO_MEMORY;
 	bar_res->end = bar_res->start + bar_size - 1;
 	/*
 	 * Allocate the number of table entries needed for BAR.
@@ -154,7 +122,7 @@ static void iomm_table_allocate_entry(st
 		++current_iomm_table_entry;
 	}
 	max_io_memory = BASE_IO_MEMORY +
-		(IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry);
+		IOMM_TABLE_ENTRY_SIZE * current_iomm_table_entry;
 	spin_unlock(&iomm_table_lock);
 }
 
@@ -171,13 +139,10 @@ static void iomm_table_allocate_entry(st
  */
 static void allocate_device_bars(struct pci_dev *dev)
 {
-	struct resource *bar_res;
 	int bar_num;
 
-	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num) {
-		bar_res = &dev->resource[bar_num];
+	for (bar_num = 0; bar_num <= PCI_ROM_RESOURCE; ++bar_num)
 		iomm_table_allocate_entry(dev, bar_num);
-	}
 }
 
 /*
@@ -205,10 +170,9 @@ static struct device_node *build_device_
 	struct device_node *node;
 	struct pci_dn *pdn;
 
-	node = kmalloc(sizeof(struct device_node), GFP_KERNEL);
+	node = kzalloc(sizeof(struct device_node), GFP_KERNEL);
 	if (node == NULL)
 		return NULL;
-	memset(node, 0, sizeof(struct device_node));
 	pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
 	if (pdn == NULL) {
 		kfree(node);
@@ -224,7 +188,7 @@ static struct device_node *build_device_
 }
 
 /*
- * unsigned long __init find_and_init_phbs(void)
+ * iSeries_pcibios_init
  *
  * Description:
  *   This function checks for all possible system PCI host bridges that connect
@@ -232,7 +196,7 @@ static struct device_node *build_device_
  *   ownership status.  A pci_controller is built for any bus which is partially
  *   owned or fully owned by this guest partition.
  */
-unsigned long __init find_and_init_phbs(void)
+void iSeries_pcibios_init(void)
 {
 	struct pci_controller *phb;
 	HvBusNumber bus;
@@ -263,18 +227,6 @@ unsigned long __init find_and_init_phbs(
 			printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
 			       bus, ret);
 	}
-	return 0;
-}
-
-/*
- * iSeries_pcibios_init
- *
- * Chance to initialize and structures or variable before PCI Bus walk.
- */
-void iSeries_pcibios_init(void)
-{
-	iomm_table_initialize();
-	find_and_init_phbs();
 }
 
 /*
@@ -331,8 +283,7 @@ static void scan_PHB_slots(struct pci_co
 	int IdSel;
 	const int MaxAgents = 8;
 
-	DevInfo = (struct HvCallPci_DeviceInfo*)
-		kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
+	DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
 	if (DevInfo == NULL)
 		return;
 
@@ -622,7 +573,6 @@ static int CheckReturnCode(char *TextHdr
 	if (ret != 0)  {
 		struct pci_dn *pdn = PCI_DN(DevNode);
 
-		++Pci_Error_Count;
 		(*retry)++;
 		printk("PCI: %s: Device 0x%04X:%02X  I/O Error(%2d): 0x%04X\n",
 				TextHdr, pdn->busno, pdn->devfn,
@@ -704,7 +654,6 @@ u8 iSeries_Read_Byte(const volatile void
 		return 0xff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad8, &ret, dsa, BarOffset, 0);
 	} while (CheckReturnCode("RDB", DevNode, &retry, ret.rc) != 0);
 
@@ -734,7 +683,6 @@ u16 iSeries_Read_Word(const volatile voi
 		return 0xffff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad16, &ret, dsa,
 				BarOffset, 0);
 	} while (CheckReturnCode("RDW", DevNode, &retry, ret.rc) != 0);
@@ -765,7 +713,6 @@ u32 iSeries_Read_Long(const volatile voi
 		return 0xffffffff;
 	}
 	do {
-		++Pci_Io_Read_Count;
 		HvCall3Ret16(HvCallPciBarLoad32, &ret, dsa,
 				BarOffset, 0);
 	} while (CheckReturnCode("RDL", DevNode, &retry, ret.rc) != 0);
@@ -803,7 +750,6 @@ void iSeries_Write_Byte(u8 data, volatil
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore8, dsa, BarOffset, data, 0);
 	} while (CheckReturnCode("WWB", DevNode, &retry, rc) != 0);
 }
@@ -831,7 +777,6 @@ void iSeries_Write_Word(u16 data, volati
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore16, dsa, BarOffset, swab16(data), 0);
 	} while (CheckReturnCode("WWW", DevNode, &retry, rc) != 0);
 }
@@ -859,7 +804,6 @@ void iSeries_Write_Long(u32 data, volati
 		return;
 	}
 	do {
-		++Pci_Io_Write_Count;
 		rc = HvCall4(HvCallPciBarStore32, dsa, BarOffset, swab32(data), 0);
 	} while (CheckReturnCode("WWL", DevNode, &retry, rc) != 0);
 }
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
@ 2006-05-19  6:43 ` Stephen Rothwell
  2006-05-19  6:46 ` [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree Stephen Rothwell
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:43 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

This function was removed during iSeries cleanup but will prove useful
in the following patches.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/call_pci.h |   19 +++++++++++++++++++
 1 files changed, 19 insertions(+), 0 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

59ad1dcb0d8d81e3a96f869109315652abf271f7
diff --git a/arch/powerpc/platforms/iseries/call_pci.h b/arch/powerpc/platforms/iseries/call_pci.h
index 59d4e0a..dbdf698 100644
--- a/arch/powerpc/platforms/iseries/call_pci.h
+++ b/arch/powerpc/platforms/iseries/call_pci.h
@@ -145,6 +145,25 @@ static inline u64 HvCallPci_configLoad16
 	return retVal.rc;
 }
 
+static inline u64 HvCallPci_configLoad32(u16 busNumber, u8 subBusNumber,
+		u8 deviceId, u32 offset, u32 *value)
+{
+	struct HvCallPci_DsaAddr dsa;
+	struct HvCallPci_LoadReturn retVal;
+
+	*((u64*)&dsa) = 0;
+
+	dsa.busNumber = busNumber;
+	dsa.subBusNumber = subBusNumber;
+	dsa.deviceId = deviceId;
+
+	HvCall3Ret16(HvCallPciConfigLoad32, &retVal, *(u64 *)&dsa, offset, 0);
+
+	*value = retVal.value;
+
+	return retVal.rc;
+}
+
 static inline u64 HvCallPci_configStore8(u16 busNumber, u8 subBusNumber,
 		u8 deviceId, u32 offset, u8 value)
 {
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
  2006-05-19  6:43 ` [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32 Stephen Rothwell
@ 2006-05-19  6:46 ` Stephen Rothwell
  2006-05-19  6:48 ` [PATCH 04/14] powerpc: remove iSeries_Global_Device_List Stephen Rothwell
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:46 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

Move the probing of PCI devices to setup.c and put them all into the
flattened device tree.  The later probing is now done by traversing the
device tree.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/irq.c   |    7 -
 arch/powerpc/platforms/iseries/irq.h   |    2 
 arch/powerpc/platforms/iseries/pci.c   |  273 +++++++++-----------------------
 arch/powerpc/platforms/iseries/setup.c |  204 ++++++++++++++++++++++++
 4 files changed, 286 insertions(+), 200 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

97c92bf9859c9d883da1b8459f62dec2ab20804e
diff --git a/arch/powerpc/platforms/iseries/irq.c b/arch/powerpc/platforms/iseries/irq.c
index be3fbfc..62bbbcf 100644
--- a/arch/powerpc/platforms/iseries/irq.c
+++ b/arch/powerpc/platforms/iseries/irq.c
@@ -42,6 +42,7 @@ #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/it_lp_queue.h>
 
 #include "irq.h"
+#include "pci.h"
 #include "call_pci.h"
 
 #if defined(CONFIG_SMP)
@@ -312,12 +313,12 @@ static hw_irq_controller iSeries_IRQ_han
  * Note that sub_bus is always 0 (at the moment at least).
  */
 int __init iSeries_allocate_IRQ(HvBusNumber bus,
-		HvSubBusNumber sub_bus, HvAgentId dev_id)
+		HvSubBusNumber sub_bus, u32 bsubbus)
 {
 	int virtirq;
 	unsigned int realirq;
-	u8 idsel = (dev_id >> 4);
-	u8 function = dev_id & 7;
+	u8 idsel = ISERIES_GET_DEVICE_FROM_SUBBUS(bsubbus);
+	u8 function = ISERIES_GET_FUNCTION_FROM_SUBBUS(bsubbus);
 
 	realirq = (((((sub_bus << 8) + (bus - 1)) << 3) + (idsel - 1)) << 3)
 		+ function;
diff --git a/arch/powerpc/platforms/iseries/irq.h b/arch/powerpc/platforms/iseries/irq.h
index b9c801b..188aa80 100644
--- a/arch/powerpc/platforms/iseries/irq.h
+++ b/arch/powerpc/platforms/iseries/irq.h
@@ -2,7 +2,7 @@ #ifndef	_ISERIES_IRQ_H
 #define	_ISERIES_IRQ_H
 
 extern void iSeries_init_IRQ(void);
-extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, HvAgentId);
+extern int  iSeries_allocate_IRQ(HvBusNumber, HvSubBusNumber, u32);
 extern void iSeries_activate_IRQs(void);
 extern int iSeries_get_irq(struct pt_regs *);
 
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 91a9474..9d571e7 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -49,14 +49,9 @@ #include "call_pci.h"
  * Forward declares of prototypes.
  */
 static struct device_node *find_Device_Node(int bus, int devfn);
-static void scan_PHB_slots(struct pci_controller *Phb);
-static void scan_EADS_bridge(HvBusNumber Bus, HvSubBusNumber SubBus, int IdSel);
-static int scan_bridge_slot(HvBusNumber Bus, struct HvCallPci_BridgeInfo *Info);
 
 LIST_HEAD(iSeries_Global_Device_List);
 
-static int DeviceCount;
-
 static int Pci_Retry_Max = 3;	/* Only retry 3 times  */
 static int Pci_Error_Flag = 1;	/* Set Retry Error on. */
 
@@ -162,32 +157,6 @@ static void pci_Log_Error(char *Error_Te
 }
 
 /*
- * build_device_node(u16 Bus, int SubBus, u8 DevFn)
- */
-static struct device_node *build_device_node(HvBusNumber Bus,
-		HvSubBusNumber SubBus, int AgentId, int Function)
-{
-	struct device_node *node;
-	struct pci_dn *pdn;
-
-	node = kzalloc(sizeof(struct device_node), GFP_KERNEL);
-	if (node == NULL)
-		return NULL;
-	pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
-	if (pdn == NULL) {
-		kfree(node);
-		return NULL;
-	}
-	node->data = pdn;
-	pdn->node = node;
-	list_add_tail(&pdn->Device_List, &iSeries_Global_Device_List);
-	pdn->busno = Bus;
-	pdn->bussubno = SubBus;
-	pdn->devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(AgentId), Function);
-	return node;
-}
-
-/*
  * iSeries_pcibios_init
  *
  * Description:
@@ -199,33 +168,86 @@ static struct device_node *build_device_
 void iSeries_pcibios_init(void)
 {
 	struct pci_controller *phb;
-	HvBusNumber bus;
-
-	/* Check all possible buses. */
-	for (bus = 0; bus < 256; bus++) {
-		int ret = HvCallXm_testBus(bus);
-		if (ret == 0) {
-			printk("bus %d appears to exist\n", bus);
-
-			phb = pcibios_alloc_controller(NULL);
-			if (phb == NULL)
-				return -ENOMEM;
+	struct device_node *node;
+	struct device_node *dn;
+
+	for_each_node_by_type(node, "pci") {
+		HvBusNumber bus;
+		u32 *busp;
+
+		busp = (u32 *)get_property(node, "bus-range", NULL);
+		if (busp == NULL)
+			continue;
+		bus = *busp;
+		printk("bus %d appears to exist\n", bus);
+		phb = pcibios_alloc_controller(node);
+		if (phb == NULL)
+			continue;
+
+		phb->pci_mem_offset = phb->local_number = bus;
+		phb->first_busno = bus;
+		phb->last_busno = bus;
+		phb->ops = &iSeries_pci_ops;
+
+		/* Find and connect the devices. */
+		for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
+			struct pci_dn *pdn;
+			u8 irq;
+			int err;
+			u32 *agent;
+			u32 *reg;
+			u32 *lsn;
+
+			reg = (u32 *)get_property(dn, "reg", NULL);
+			if (reg == NULL) {
+				printk(KERN_DEBUG "no reg property!\n");
+				continue;
+			}
+			busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+			if (busp == NULL) {
+				printk(KERN_DEBUG "no subbus property!\n");
+				continue;
+			}
+			agent = (u32 *)get_property(dn, "linux,agent-id", NULL);
+			if (agent == NULL) {
+				printk(KERN_DEBUG "no agent-id\n");
+				continue;
+			}
+			lsn = (u32 *)get_property(dn,
+					"linux,logical-slot-number", NULL);
+			if (lsn == NULL) {
+				printk(KERN_DEBUG "no logical-slot-number\n");
+				continue;
+			}
 
-			phb->pci_mem_offset = phb->local_number = bus;
-			phb->first_busno = bus;
-			phb->last_busno = bus;
-			phb->ops = &iSeries_pci_ops;
+			irq = iSeries_allocate_IRQ(bus, 0, *busp);
+			err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq);
+			if (err) {
+				pci_Log_Error("Connect Bus Unit",
+					      bus, *busp, *agent, err);
+				continue;
+			}
+			err = HvCallPci_configStore8(bus, *busp, *agent,
+					PCI_INTERRUPT_LINE, irq);
+			if (err) {
+				pci_Log_Error("PciCfgStore Irq Failed!",
+						bus, *busp, *agent, err);
+				continue;
+			}
 
-			/* Find and connect the devices. */
-			scan_PHB_slots(phb);
+			pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
+			if (pdn == NULL)
+				return;
+			dn->data = pdn;
+			pdn->node = dn;
+			pdn->busno = bus;
+			pdn->devfn = (reg[0] >> 8) & 0xff;
+			pdn->bussubno = *busp;
+			pdn->Irq = irq;
+			pdn->LogicalSlot = *lsn;
+			list_add_tail(&pdn->Device_List,
+					&iSeries_Global_Device_List);
 		}
-		/*
-		 * Check for Unexpected Return code, a clue that something
-		 * has gone wrong.
-		 */
-		else if (ret != 0x0301)
-			printk(KERN_ERR "Unexpected Return on Probe(0x%04X): 0x%04X",
-			       bus, ret);
 	}
 }
 
@@ -272,147 +294,6 @@ void pcibios_fixup_resources(struct pci_
 }
 
 /*
- * Loop through each node function to find usable EADs bridges.
- */
-static void scan_PHB_slots(struct pci_controller *Phb)
-{
-	struct HvCallPci_DeviceInfo *DevInfo;
-	HvBusNumber bus = Phb->local_number;	/* System Bus */
-	const HvSubBusNumber SubBus = 0;	/* EADs is always 0. */
-	int HvRc = 0;
-	int IdSel;
-	const int MaxAgents = 8;
-
-	DevInfo = kmalloc(sizeof(struct HvCallPci_DeviceInfo), GFP_KERNEL);
-	if (DevInfo == NULL)
-		return;
-
-	/*
-	 * Probe for EADs Bridges
-	 */
-	for (IdSel = 1; IdSel < MaxAgents; ++IdSel) {
-		HvRc = HvCallPci_getDeviceInfo(bus, SubBus, IdSel,
-				iseries_hv_addr(DevInfo),
-				sizeof(struct HvCallPci_DeviceInfo));
-		if (HvRc == 0) {
-			if (DevInfo->deviceType == HvCallPci_NodeDevice)
-				scan_EADS_bridge(bus, SubBus, IdSel);
-			else
-				printk("PCI: Invalid System Configuration(0x%02X)"
-				       " for bus 0x%02x id 0x%02x.\n",
-				       DevInfo->deviceType, bus, IdSel);
-		}
-		else
-			pci_Log_Error("getDeviceInfo", bus, SubBus, IdSel, HvRc);
-	}
-	kfree(DevInfo);
-}
-
-static void scan_EADS_bridge(HvBusNumber bus, HvSubBusNumber SubBus,
-		int IdSel)
-{
-	struct HvCallPci_BridgeInfo *BridgeInfo;
-	HvAgentId AgentId;
-	int Function;
-	int HvRc;
-
-	BridgeInfo = (struct HvCallPci_BridgeInfo *)
-		kmalloc(sizeof(struct HvCallPci_BridgeInfo), GFP_KERNEL);
-	if (BridgeInfo == NULL)
-		return;
-
-	/* Note: hvSubBus and irq is always be 0 at this level! */
-	for (Function = 0; Function < 8; ++Function) {
-		AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
-		HvRc = HvCallXm_connectBusUnit(bus, SubBus, AgentId, 0);
-		if (HvRc == 0) {
-			printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
-			       bus, IdSel, Function, AgentId);
-			/*  Connect EADs: 0x18.00.12 = 0x00 */
-			HvRc = HvCallPci_getBusUnitInfo(bus, SubBus, AgentId,
-					iseries_hv_addr(BridgeInfo),
-					sizeof(struct HvCallPci_BridgeInfo));
-			if (HvRc == 0) {
-				printk("bridge info: type %x subbus %x maxAgents %x maxsubbus %x logslot %x\n",
-					BridgeInfo->busUnitInfo.deviceType,
-					BridgeInfo->subBusNumber,
-					BridgeInfo->maxAgents,
-					BridgeInfo->maxSubBusNumber,
-					BridgeInfo->logicalSlotNumber);
-				if (BridgeInfo->busUnitInfo.deviceType ==
-						HvCallPci_BridgeDevice)  {
-					/* Scan_Bridge_Slot...: 0x18.00.12 */
-					scan_bridge_slot(bus, BridgeInfo);
-				} else
-					printk("PCI: Invalid Bridge Configuration(0x%02X)",
-						BridgeInfo->busUnitInfo.deviceType);
-			}
-		} else if (HvRc != 0x000B)
-			pci_Log_Error("EADs Connect",
-					bus, SubBus, AgentId, HvRc);
-	}
-	kfree(BridgeInfo);
-}
-
-/*
- * This assumes that the node slot is always on the primary bus!
- */
-static int scan_bridge_slot(HvBusNumber Bus,
-		struct HvCallPci_BridgeInfo *BridgeInfo)
-{
-	struct device_node *node;
-	HvSubBusNumber SubBus = BridgeInfo->subBusNumber;
-	u16 VendorId = 0;
-	int HvRc = 0;
-	u8 Irq = 0;
-	int IdSel = ISERIES_GET_DEVICE_FROM_SUBBUS(SubBus);
-	int Function = ISERIES_GET_FUNCTION_FROM_SUBBUS(SubBus);
-	HvAgentId EADsIdSel = ISERIES_PCI_AGENTID(IdSel, Function);
-
-	/* iSeries_allocate_IRQ.: 0x18.00.12(0xA3) */
-	Irq = iSeries_allocate_IRQ(Bus, 0, EADsIdSel);
-
-	/*
-	 * Connect all functions of any device found.
-	 */
-	for (IdSel = 1; IdSel <= BridgeInfo->maxAgents; ++IdSel) {
-		for (Function = 0; Function < 8; ++Function) {
-			HvAgentId AgentId = ISERIES_PCI_AGENTID(IdSel, Function);
-			HvRc = HvCallXm_connectBusUnit(Bus, SubBus,
-					AgentId, Irq);
-			if (HvRc != 0) {
-				pci_Log_Error("Connect Bus Unit",
-					      Bus, SubBus, AgentId, HvRc);
-				continue;
-			}
-
-			HvRc = HvCallPci_configLoad16(Bus, SubBus, AgentId,
-						      PCI_VENDOR_ID, &VendorId);
-			if (HvRc != 0) {
-				pci_Log_Error("Read Vendor",
-					      Bus, SubBus, AgentId, HvRc);
-				continue;
-			}
-			printk("read vendor ID: %x\n", VendorId);
-
-			/* FoundDevice: 0x18.28.10 = 0x12AE */
-			HvRc = HvCallPci_configStore8(Bus, SubBus, AgentId,
-						      PCI_INTERRUPT_LINE, Irq);
-			if (HvRc != 0)
-				pci_Log_Error("PciCfgStore Irq Failed!",
-					      Bus, SubBus, AgentId, HvRc);
-
-			++DeviceCount;
-			node = build_device_node(Bus, SubBus, EADsIdSel, Function);
-			PCI_DN(node)->Irq = Irq;
-			PCI_DN(node)->LogicalSlot = BridgeInfo->logicalSlotNumber;
-
-		} /* for (Function = 0; Function < 8; ++Function) */
-	} /* for (IdSel = 1; IdSel <= MaxAgents; ++IdSel) */
-	return HvRc;
-}
-
-/*
  * I/0 Memory copy MUST use mmio commands on iSeries
  * To do; For performance, include the hv call directly
  */
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index fd6d0eb..d83f5ed 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -66,6 +66,8 @@ #include "processor_vpd.h"
 #include "main_store.h"
 #include "call_sm.h"
 #include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -1000,6 +1002,207 @@ void dt_vdevices(struct iseries_flat_dt 
 	dt_end_node(dt);
 }
 
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus,
+		struct HvCallPci_BridgeInfo *bridge_info)
+{
+	HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+	u16 vendor_id;
+	u16 device_id;
+	u32 class_id;
+	int err;
+	char buf[32];
+	u32 reg[5];
+	int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+	int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+	HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+
+	/*
+	 * Connect all functions of any device found.
+	 */
+	for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+		for (function = 0; function < 8; function++) {
+			u8 devfn;
+
+			HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+					function);
+			err = HvCallXm_connectBusUnit(bus, sub_bus,
+					agent_id, 0);
+			if (err) {
+				if (err != 0x302)
+					printk(KERN_DEBUG
+						"connectBusUnit(%x, %x, %x) "
+						"== %x\n",
+						bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_VENDOR_ID, &vendor_id);
+			if (err) {
+				printk(KERN_DEBUG
+					"ReadVendor(%x, %x, %x) == %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_DEVICE_ID, &device_id);
+			if (err) {
+				printk(KERN_DEBUG
+					"ReadDevice(%x, %x, %x) == %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+					PCI_CLASS_REVISION , &class_id);
+			if (err) {
+				printk(KERN_DEBUG
+					"ReadClass(%x, %x, %x) == %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+					function);
+			if (function == 0)
+				snprintf(buf, sizeof(buf), "pci@%x",
+						PCI_SLOT(devfn));
+			else
+				snprintf(buf, sizeof(buf), "pci@%x,%d",
+						PCI_SLOT(devfn), function);
+			dt_start_node(dt, buf);
+			reg[0] = (bus << 18) | (devfn << 8);
+			reg[1] = 0;
+			reg[2] = 0;
+			reg[3] = 0;
+			reg[4] = 0;
+			dt_prop_u32_list(dt, "reg", reg, 5);
+			dt_prop_u32(dt, "vendor-id", vendor_id);
+			dt_prop_u32(dt, "device-id", device_id);
+			dt_prop_u32(dt, "class-code", class_id >> 8);
+			dt_prop_u32(dt, "revision-id", class_id & 0xff);
+			dt_prop_u32(dt, "linux,subbus", sub_bus);
+			dt_prop_u32(dt, "linux,agent-id", agent_id);
+			dt_prop_u32(dt, "linux,logical-slot-number",
+					bridge_info->logicalSlotNumber);
+			dt_end_node(dt);
+
+		}
+	}
+}
+
+static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+		HvSubBusNumber sub_bus, int id_sel)
+{
+	struct HvCallPci_BridgeInfo bridge_info;
+	HvAgentId agent_id;
+	int function;
+	int ret;
+
+	/* Note: hvSubBus and irq is always be 0 at this level! */
+	for (function = 0; function < 8; ++function) {
+		agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+		ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+		if (ret != 0) {
+			if (ret != 0xb)
+				printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
+						"== %x\n",
+						bus, sub_bus, agent_id, ret);
+			continue;
+		}
+		printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+				bus, id_sel, function, agent_id);
+		ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+				iseries_hv_addr(&bridge_info),
+				sizeof(struct HvCallPci_BridgeInfo));
+		if (ret != 0)
+			continue;
+		printk("bridge info: type %x subbus %x "
+			"maxAgents %x maxsubbus %x logslot %x\n",
+			bridge_info.busUnitInfo.deviceType,
+			bridge_info.subBusNumber,
+			bridge_info.maxAgents,
+			bridge_info.maxSubBusNumber,
+			bridge_info.logicalSlotNumber);
+		if (bridge_info.busUnitInfo.deviceType ==
+				HvCallPci_BridgeDevice)
+			scan_bridge_slot(dt, bus, &bridge_info);
+		else
+			printk("PCI: Invalid Bridge Configuration(0x%02X)",
+				bridge_info.busUnitInfo.deviceType);
+	}
+}
+
+static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+	struct HvCallPci_DeviceInfo dev_info;
+	const HvSubBusNumber sub_bus = 0;	/* EADs is always 0. */
+	int err;
+	int id_sel;
+	const int max_agents = 8;
+
+	/*
+	 * Probe for EADs Bridges
+	 */
+	for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+		err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+				iseries_hv_addr(&dev_info),
+				sizeof(struct HvCallPci_DeviceInfo));
+		if (err) {
+			if (err != 0x302)
+				printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
+						"== %x\n",
+						bus, sub_bus, id_sel, err);
+			continue;
+		}
+		if (dev_info.deviceType != HvCallPci_NodeDevice) {
+			printk(KERN_DEBUG "PCI: Invalid System Configuration"
+					"(0x%02X) for bus 0x%02x id 0x%02x.\n",
+					dev_info.deviceType, bus, id_sel);
+			continue;
+		}
+		scan_bridge(dt, bus, sub_bus, id_sel);
+	}
+}
+
+static void dt_pci_devices(struct iseries_flat_dt *dt)
+{
+	HvBusNumber bus;
+	char buf[32];
+	u32 buses[2];
+	int phb_num = 0;
+
+	/* Check all possible buses. */
+	for (bus = 0; bus < 256; bus++) {
+		int err = HvCallXm_testBus(bus);
+
+		if (err) {
+			/*
+			 * Check for Unexpected Return code, a clue that
+			 * something has gone wrong.
+			 */
+			if (err != 0x0301)
+				printk(KERN_ERR "Unexpected Return on Probe"
+						"(0x%02X): 0x%04X", bus, err);
+			continue;
+		}
+		printk("bus %d appears to exist\n", bus);
+		snprintf(buf, 32, "pci@%d", phb_num);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", "pci");
+		dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+		dt_prop_u32(dt, "#address-cells", 3);
+		dt_prop_u32(dt, "#size-cells", 2);
+		buses[0] = buses[1] = bus;
+		dt_prop_u32_list(dt, "bus-range", buses, 2);
+		scan_phb(dt, bus);
+		dt_end_node(dt);
+		phb_num++;
+	}
+}
+
 void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
 {
 	u64 tmp[2];
@@ -1029,6 +1232,7 @@ void build_flat_dt(struct iseries_flat_d
 	dt_cpus(dt);
 
 	dt_vdevices(dt);
+	dt_pci_devices(dt);
 
 	dt_end_node(dt);
 
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 04/14] powerpc: remove iSeries_Global_Device_List
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
  2006-05-19  6:43 ` [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32 Stephen Rothwell
  2006-05-19  6:46 ` [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree Stephen Rothwell
@ 2006-05-19  6:48 ` Stephen Rothwell
  2006-05-19  6:50 ` [PATCH 05/14] powerpc: remove Irq from pci_dn Stephen Rothwell
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:48 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

We can now scan the list of device nodes instead.  This also allows us
to remove the Device_list member of struct pci_dn.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/iommu.c |   15 +++++++++------
 arch/powerpc/platforms/iseries/pci.c   |   14 ++++++--------
 include/asm-powerpc/pci-bridge.h       |    1 -
 3 files changed, 15 insertions(+), 15 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

80052bf80f481996ffec6dddc8fab45bb36db0a3
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 3ac2206..75a5a1e 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -32,13 +32,11 @@ #include <asm/iommu.h>
 #include <asm/tce.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
+#include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/iommu.h>
 
-extern struct list_head iSeries_Global_Device_List;
-
-
 static void tce_build_iSeries(struct iommu_table *tbl, long index, long npages,
 		unsigned long uaddr, enum dma_data_direction direction)
 {
@@ -140,10 +138,15 @@ #ifdef CONFIG_PCI
  */
 static struct iommu_table *iommu_table_find(struct iommu_table * tbl)
 {
-	struct pci_dn *pdn;
+	struct device_node *node;
+
+	for (node = NULL; (node = of_find_all_nodes(node)); ) {
+		struct pci_dn *pdn = PCI_DN(node);
+		struct iommu_table *it;
 
-	list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
-		struct iommu_table *it = pdn->iommu_table;
+		if (pdn == NULL)
+			continue;
+		it = pdn->iommu_table;
 		if ((it != NULL) &&
 		    (it->it_type == TCE_PCI) &&
 		    (it->it_offset == tbl->it_offset) &&
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 9d571e7..5bc08d4 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -50,8 +50,6 @@ #include "call_pci.h"
  */
 static struct device_node *find_Device_Node(int bus, int devfn);
 
-LIST_HEAD(iSeries_Global_Device_List);
-
 static int Pci_Retry_Max = 3;	/* Only retry 3 times  */
 static int Pci_Error_Flag = 1;	/* Set Retry Error on. */
 
@@ -245,8 +243,6 @@ void iSeries_pcibios_init(void)
 			pdn->bussubno = *busp;
 			pdn->Irq = irq;
 			pdn->LogicalSlot = *lsn;
-			list_add_tail(&pdn->Device_List,
-					&iSeries_Global_Device_List);
 		}
 	}
 }
@@ -338,11 +334,13 @@ EXPORT_SYMBOL(iSeries_memcpy_fromio);
  */
 static struct device_node *find_Device_Node(int bus, int devfn)
 {
-	struct pci_dn *pdn;
+	struct device_node *node;
+
+	for (node = NULL; (node = of_find_all_nodes(node)); ) {
+		struct pci_dn *pdn = PCI_DN(node);
 
-	list_for_each_entry(pdn, &iSeries_Global_Device_List, Device_List) {
-		if ((bus == pdn->busno) && (devfn == pdn->devfn))
-			return pdn->node;
+		if (pdn && (bus == pdn->busno) && (devfn == pdn->devfn))
+			return node;
 	}
 	return NULL;
 }
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 38de92d..59794b4 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -79,7 +79,6 @@ #endif
 	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
 	struct	device_node *node;	/* back-pointer to the device_node */
 #ifdef CONFIG_PPC_ISERIES
-	struct	list_head Device_List;
 	int	Irq;			/* Assigned IRQ */
 	int	Flags;			/* Possible flags(disable/bist)*/
 	u8	LogicalSlot;		/* Hv Slot Index for Tces */
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 05/14] powerpc: remove Irq from pci_dn
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (2 preceding siblings ...)
  2006-05-19  6:48 ` [PATCH 04/14] powerpc: remove iSeries_Global_Device_List Stephen Rothwell
@ 2006-05-19  6:50 ` Stephen Rothwell
  2006-05-19  6:51 ` [PATCH 06/14] powerpc: remove LogicalSlot " Stephen Rothwell
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:50 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

As we now store enough information in the device_node to allocate the
irq number in pcibios_final_fixup.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/pci.c |   53 ++++++++++++++++++----------------
 include/asm-powerpc/pci-bridge.h     |    1 -
 2 files changed, 28 insertions(+), 26 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

0a0cf362cf41de98069fb817acf23a4d041b45f4
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 5bc08d4..edaafbb 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -190,9 +190,6 @@ void iSeries_pcibios_init(void)
 		/* Find and connect the devices. */
 		for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
 			struct pci_dn *pdn;
-			u8 irq;
-			int err;
-			u32 *agent;
 			u32 *reg;
 			u32 *lsn;
 
@@ -206,11 +203,6 @@ void iSeries_pcibios_init(void)
 				printk(KERN_DEBUG "no subbus property!\n");
 				continue;
 			}
-			agent = (u32 *)get_property(dn, "linux,agent-id", NULL);
-			if (agent == NULL) {
-				printk(KERN_DEBUG "no agent-id\n");
-				continue;
-			}
 			lsn = (u32 *)get_property(dn,
 					"linux,logical-slot-number", NULL);
 			if (lsn == NULL) {
@@ -218,21 +210,6 @@ void iSeries_pcibios_init(void)
 				continue;
 			}
 
-			irq = iSeries_allocate_IRQ(bus, 0, *busp);
-			err = HvCallXm_connectBusUnit(bus, *busp, *agent, irq);
-			if (err) {
-				pci_Log_Error("Connect Bus Unit",
-					      bus, *busp, *agent, err);
-				continue;
-			}
-			err = HvCallPci_configStore8(bus, *busp, *agent,
-					PCI_INTERRUPT_LINE, irq);
-			if (err) {
-				pci_Log_Error("PciCfgStore Irq Failed!",
-						bus, *busp, *agent, err);
-				continue;
-			}
-
 			pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
 			if (pdn == NULL)
 				return;
@@ -241,7 +218,6 @@ void iSeries_pcibios_init(void)
 			pdn->busno = bus;
 			pdn->devfn = (reg[0] >> 8) & 0xff;
 			pdn->bussubno = *busp;
-			pdn->Irq = irq;
 			pdn->LogicalSlot = *lsn;
 		}
 	}
@@ -266,6 +242,34 @@ void __init iSeries_pci_final_fixup(void
 		       pdev->bus->number, pdev->devfn, node);
 
 		if (node != NULL) {
+			struct pci_dn *pdn = PCI_DN(node);
+			u32 *agent;
+
+			agent = (u32 *)get_property(node, "linux,agent-id",
+					NULL);
+			if ((pdn != NULL) && (agent != NULL)) {
+				u8 irq = iSeries_allocate_IRQ(pdn->busno, 0,
+						pdn->bussubno);
+				int err;
+
+				err = HvCallXm_connectBusUnit(pdn->busno, pdn->bussubno,
+						*agent, irq);
+				if (err)
+					pci_Log_Error("Connect Bus Unit",
+						pdn->busno, pdn->bussubno, *agent, err);
+				else {
+					err = HvCallPci_configStore8(pdn->busno, pdn->bussubno,
+							*agent,
+							PCI_INTERRUPT_LINE,
+							irq);
+					if (err)
+						pci_Log_Error("PciCfgStore Irq Failed!",
+							pdn->busno, pdn->bussubno, *agent, err);
+				}
+				if (!err)
+					pdev->irq = irq;
+			}
+
 			++DeviceCount;
 			pdev->sysdata = (void *)node;
 			PCI_DN(node)->pcidev = pdev;
@@ -275,7 +279,6 @@ void __init iSeries_pci_final_fixup(void
 		} else
 			printk("PCI: Device Tree not found for 0x%016lX\n",
 					(unsigned long)pdev);
-		pdev->irq = PCI_DN(node)->Irq;
 	}
 	iSeries_activate_IRQs();
 	mf_display_src(0xC9000200);
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 59794b4..09079e4 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -79,7 +79,6 @@ #endif
 	struct	pci_dev *pcidev;	/* back-pointer to the pci device */
 	struct	device_node *node;	/* back-pointer to the device_node */
 #ifdef CONFIG_PPC_ISERIES
-	int	Irq;			/* Assigned IRQ */
 	int	Flags;			/* Possible flags(disable/bist)*/
 	u8	LogicalSlot;		/* Hv Slot Index for Tces */
 #endif
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 06/14] powerpc: remove LogicalSlot from pci_dn
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (3 preceding siblings ...)
  2006-05-19  6:50 ` [PATCH 05/14] powerpc: remove Irq from pci_dn Stephen Rothwell
@ 2006-05-19  6:51 ` Stephen Rothwell
  2006-05-19  6:53 ` [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute Stephen Rothwell
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:51 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

As we now store enough information in the device_node.

Also the Flags field was not used either, do remove that.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/iommu.c |    5 ++++-
 arch/powerpc/platforms/iseries/pci.c   |    8 --------
 include/asm-powerpc/pci-bridge.h       |    4 ----
 3 files changed, 4 insertions(+), 13 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

bf52061e7db75eb167e5f7749d706614de5bcc81
diff --git a/arch/powerpc/platforms/iseries/iommu.c b/arch/powerpc/platforms/iseries/iommu.c
index 75a5a1e..a992f6a 100644
--- a/arch/powerpc/platforms/iseries/iommu.c
+++ b/arch/powerpc/platforms/iseries/iommu.c
@@ -162,10 +162,13 @@ void iommu_devnode_init_iSeries(struct d
 {
 	struct iommu_table *tbl;
 	struct pci_dn *pdn = PCI_DN(dn);
+	u32 *lsn = (u32 *)get_property(dn, "linux,logical-slot-number", NULL);
+
+	BUG_ON(lsn == NULL);
 
 	tbl = kmalloc(sizeof(struct iommu_table), GFP_KERNEL);
 
-	iommu_table_getparms_iSeries(pdn->busno, pdn->LogicalSlot, 0, tbl);
+	iommu_table_getparms_iSeries(pdn->busno, *lsn, 0, tbl);
 
 	/* Look for existing tce table */
 	pdn->iommu_table = iommu_table_find(tbl);
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index edaafbb..86a8698 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -191,7 +191,6 @@ void iSeries_pcibios_init(void)
 		for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
 			struct pci_dn *pdn;
 			u32 *reg;
-			u32 *lsn;
 
 			reg = (u32 *)get_property(dn, "reg", NULL);
 			if (reg == NULL) {
@@ -203,12 +202,6 @@ void iSeries_pcibios_init(void)
 				printk(KERN_DEBUG "no subbus property!\n");
 				continue;
 			}
-			lsn = (u32 *)get_property(dn,
-					"linux,logical-slot-number", NULL);
-			if (lsn == NULL) {
-				printk(KERN_DEBUG "no logical-slot-number\n");
-				continue;
-			}
 
 			pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
 			if (pdn == NULL)
@@ -218,7 +211,6 @@ void iSeries_pcibios_init(void)
 			pdn->busno = bus;
 			pdn->devfn = (reg[0] >> 8) & 0xff;
 			pdn->bussubno = *busp;
-			pdn->LogicalSlot = *lsn;
 		}
 	}
 }
diff --git a/include/asm-powerpc/pci-bridge.h b/include/asm-powerpc/pci-bridge.h
index 09079e4..84a3075 100644
--- a/include/asm-powerpc/pci-bridge.h
+++ b/include/asm-powerpc/pci-bridge.h
@@ -78,10 +78,6 @@ #endif
 	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 */
-#ifdef CONFIG_PPC_ISERIES
-	int	Flags;			/* Possible flags(disable/bist)*/
-	u8	LogicalSlot;		/* Hv Slot Index for Tces */
-#endif
 	u32	config_space[16];	/* saved PCI config space */
 };
 
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (4 preceding siblings ...)
  2006-05-19  6:51 ` [PATCH 06/14] powerpc: remove LogicalSlot " Stephen Rothwell
@ 2006-05-19  6:53 ` Stephen Rothwell
  2006-05-19  6:54 ` [PATCH 08/14] powerpc: clean up iSeries PCI probe Stephen Rothwell
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:53 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev


Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/kernel/pci_64.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

bfe21d083414576fccd84ead574adffea99968c1
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index e1b3b3e..30a4e6a 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -886,8 +886,8 @@ int pci_mmap_page_range(struct pci_dev *
 	return ret;
 }
 
-#ifdef CONFIG_PPC_MULTIPLATFORM
-static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t pci_show_devspec(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
 	struct pci_dev *pdev;
 	struct device_node *np;
@@ -899,13 +899,10 @@ static ssize_t pci_show_devspec(struct d
 	return sprintf(buf, "%s", np->full_name);
 }
 static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 
 void pcibios_add_platform_entries(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PPC_MULTIPLATFORM
 	device_create_file(&pdev->dev, &dev_attr_devspec);
-#endif /* CONFIG_PPC_MULTIPLATFORM */
 }
 
 #ifdef CONFIG_PPC_MULTIPLATFORM
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 08/14] powerpc: clean up iSeries PCI probe
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (5 preceding siblings ...)
  2006-05-19  6:53 ` [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute Stephen Rothwell
@ 2006-05-19  6:54 ` Stephen Rothwell
  2006-05-19  6:55 ` [PATCH 09/14] powerpc: make iSeries flat device tree stuff static Stephen Rothwell
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:54 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev


Only scan the host bridges and then use the existing pci_devs_phb_init()
routine.

Also fix typo in setup of reg property.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/kernel/pci_dn.c           |    6 +++++
 arch/powerpc/platforms/iseries/pci.c   |   42 +++++++++++---------------------
 arch/powerpc/platforms/iseries/setup.c |    2 +-
 3 files changed, 21 insertions(+), 29 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

979e33e7df3519bb4bbc550ad7e52b5ad2b30221
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c
index 12c4c9e..1c18953 100644
--- a/arch/powerpc/kernel/pci_dn.c
+++ b/arch/powerpc/kernel/pci_dn.c
@@ -31,6 +31,7 @@ #include <asm/prom.h>
 #include <asm/pci-bridge.h>
 #include <asm/pSeries_reconfig.h>
 #include <asm/ppc-pci.h>
+#include <asm/firmware.h>
 
 /*
  * Traverse_func that inits the PCI fields of the device node.
@@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_in
 		pdn->busno = (regs[0] >> 16) & 0xff;
 		pdn->devfn = (regs[0] >> 8) & 0xff;
 	}
+	if (firmware_has_feature(FW_FEATURE_ISERIES)) {
+		u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL);
+		if (busp)
+			pdn->bussubno = *busp;
+	}
 
 	pdn->pci_ext_config_space = (type && *type == 1);
 	return NULL;
diff --git a/arch/powerpc/platforms/iseries/pci.c b/arch/powerpc/platforms/iseries/pci.c
index 86a8698..35bcc98 100644
--- a/arch/powerpc/platforms/iseries/pci.c
+++ b/arch/powerpc/platforms/iseries/pci.c
@@ -166,13 +166,21 @@ static void pci_Log_Error(char *Error_Te
 void iSeries_pcibios_init(void)
 {
 	struct pci_controller *phb;
-	struct device_node *node;
-	struct device_node *dn;
+	struct device_node *root = of_find_node_by_path("/");
+	struct device_node *node = NULL;
 
-	for_each_node_by_type(node, "pci") {
+	if (root == NULL) {
+		printk(KERN_CRIT "iSeries_pcibios_init: can't find root "
+				"of device tree\n");
+		return;
+	}
+	while ((node = of_get_next_child(root, node)) != NULL) {
 		HvBusNumber bus;
 		u32 *busp;
 
+		if ((node->type == NULL) || (strcmp(node->type, "pci") != 0))
+			continue;
+
 		busp = (u32 *)get_property(node, "bus-range", NULL);
 		if (busp == NULL)
 			continue;
@@ -186,33 +194,11 @@ void iSeries_pcibios_init(void)
 		phb->first_busno = bus;
 		phb->last_busno = bus;
 		phb->ops = &iSeries_pci_ops;
+	}
 
-		/* Find and connect the devices. */
-		for (dn = NULL; (dn = of_get_next_child(node, dn)) != NULL;) {
-			struct pci_dn *pdn;
-			u32 *reg;
-
-			reg = (u32 *)get_property(dn, "reg", NULL);
-			if (reg == NULL) {
-				printk(KERN_DEBUG "no reg property!\n");
-				continue;
-			}
-			busp = (u32 *)get_property(dn, "linux,subbus", NULL);
-			if (busp == NULL) {
-				printk(KERN_DEBUG "no subbus property!\n");
-				continue;
-			}
+	of_node_put(root);
 
-			pdn = kzalloc(sizeof(*pdn), GFP_KERNEL);
-			if (pdn == NULL)
-				return;
-			dn->data = pdn;
-			pdn->node = dn;
-			pdn->busno = bus;
-			pdn->devfn = (reg[0] >> 8) & 0xff;
-			pdn->bussubno = *busp;
-		}
-	}
+	pci_devs_phb_init();
 }
 
 /*
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index d83f5ed..0f49412 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -1073,7 +1073,7 @@ static void scan_bridge_slot(struct iser
 				snprintf(buf, sizeof(buf), "pci@%x,%d",
 						PCI_SLOT(devfn), function);
 			dt_start_node(dt, buf);
-			reg[0] = (bus << 18) | (devfn << 8);
+			reg[0] = (bus << 16) | (devfn << 8);
 			reg[1] = 0;
 			reg[2] = 0;
 			reg[3] = 0;
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 09/14] powerpc: make iSeries flat device tree stuff static
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (6 preceding siblings ...)
  2006-05-19  6:54 ` [PATCH 08/14] powerpc: clean up iSeries PCI probe Stephen Rothwell
@ 2006-05-19  6:55 ` Stephen Rothwell
  2006-05-19  6:58 ` [PATCH 10/14] powerpc: give iSeries device tree nodes better names Stephen Rothwell
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:55 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev


Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/setup.c |   40 ++++++++++++++++++--------------
 1 files changed, 22 insertions(+), 18 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

ef5523ad5d01ff256b792ef5a44719c4a56771d9
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 0f49412..9586414 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -723,9 +723,9 @@ struct iseries_flat_dt {
 	struct blob strings;
 };
 
-struct iseries_flat_dt iseries_dt;
+static struct iseries_flat_dt iseries_dt;
 
-void dt_init(struct iseries_flat_dt *dt)
+static void dt_init(struct iseries_flat_dt *dt)
 {
 	dt->header.off_mem_rsvmap =
 		offsetof(struct iseries_flat_dt, reserve_map);
@@ -748,7 +748,7 @@ void dt_init(struct iseries_flat_dt *dt)
 	dt->reserve_map[1] = 0;
 }
 
-void dt_check_blob(struct blob *b)
+static void dt_check_blob(struct blob *b)
 {
 	if (b->next >= (unsigned long)&b->next) {
 		DBG("Ran out of space in flat device tree blob!\n");
@@ -756,7 +756,7 @@ void dt_check_blob(struct blob *b)
 	}
 }
 
-void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+static void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
 {
 	*((u32*)dt->dt.next) = value;
 	dt->dt.next += sizeof(u32);
@@ -764,15 +764,17 @@ void dt_push_u32(struct iseries_flat_dt 
 	dt_check_blob(&dt->dt);
 }
 
-void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+#ifdef notyet
+static void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
 {
 	*((u64*)dt->dt.next) = value;
 	dt->dt.next += sizeof(u64);
 
 	dt_check_blob(&dt->dt);
 }
+#endif
 
-unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
+static unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
 {
 	unsigned long start = blob->next - (unsigned long)blob->data;
 
@@ -784,7 +786,7 @@ unsigned long dt_push_bytes(struct blob 
 	return start;
 }
 
-void dt_start_node(struct iseries_flat_dt *dt, char *name)
+static void dt_start_node(struct iseries_flat_dt *dt, char *name)
 {
 	dt_push_u32(dt, OF_DT_BEGIN_NODE);
 	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
@@ -792,7 +794,7 @@ void dt_start_node(struct iseries_flat_d
 
 #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
 
-void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
+static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
 {
 	unsigned long offset;
 
@@ -811,37 +813,39 @@ void dt_prop(struct iseries_flat_dt *dt,
 	dt_push_bytes(&dt->dt, data, len);
 }
 
-void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
+static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
 {
 	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
 }
 
-void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
 {
 	dt_prop(dt, name, (char *)&data, sizeof(u32));
 }
 
-void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
 {
 	dt_prop(dt, name, (char *)&data, sizeof(u64));
 }
 
-void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
+static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
 {
 	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
 }
 
-void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
+static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
 {
 	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
 }
 
-void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+#ifdef notyet
+static void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
 {
 	dt_prop(dt, name, NULL, 0);
 }
+#endif
 
-void dt_cpus(struct iseries_flat_dt *dt)
+static void dt_cpus(struct iseries_flat_dt *dt)
 {
 	unsigned char buf[32];
 	unsigned char *p;
@@ -895,7 +899,7 @@ void dt_cpus(struct iseries_flat_dt *dt)
 	dt_end_node(dt);
 }
 
-void dt_model(struct iseries_flat_dt *dt)
+static void dt_model(struct iseries_flat_dt *dt)
 {
 	char buf[16] = "IBM,";
 
@@ -913,7 +917,7 @@ void dt_model(struct iseries_flat_dt *dt
 	dt_prop_str(dt, "compatible", "IBM,iSeries");
 }
 
-void dt_vdevices(struct iseries_flat_dt *dt)
+static void dt_vdevices(struct iseries_flat_dt *dt)
 {
 	u32 reg = 0;
 	HvLpIndexMap vlan_map;
@@ -1203,7 +1207,7 @@ static void dt_pci_devices(struct iserie
 	}
 }
 
-void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
+static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
 {
 	u64 tmp[2];
 
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 10/14] powerpc: give iSeries device tree nodes better names
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (7 preceding siblings ...)
  2006-05-19  6:55 ` [PATCH 09/14] powerpc: make iSeries flat device tree stuff static Stephen Rothwell
@ 2006-05-19  6:58 ` Stephen Rothwell
  2006-05-19  7:00 ` [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c Stephen Rothwell
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  6:58 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

Use the PCI class code to choose a name for the PCI device nodes and
to guess a device_type.  Failing that, base the name on the vendor and
device ids as specified in the spec.

Mark just about everything __init{data}.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/setup.c |   95 ++++++++++++++++++++++----------
 1 files changed, 66 insertions(+), 29 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

753e3e7ff975a03dbcc5a761041f0f855215e7c5
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 9586414..5661bd0 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -725,7 +725,7 @@ struct iseries_flat_dt {
 
 static struct iseries_flat_dt iseries_dt;
 
-static void dt_init(struct iseries_flat_dt *dt)
+static void __init dt_init(struct iseries_flat_dt *dt)
 {
 	dt->header.off_mem_rsvmap =
 		offsetof(struct iseries_flat_dt, reserve_map);
@@ -748,7 +748,7 @@ static void dt_init(struct iseries_flat_
 	dt->reserve_map[1] = 0;
 }
 
-static void dt_check_blob(struct blob *b)
+static void __init dt_check_blob(struct blob *b)
 {
 	if (b->next >= (unsigned long)&b->next) {
 		DBG("Ran out of space in flat device tree blob!\n");
@@ -756,7 +756,7 @@ static void dt_check_blob(struct blob *b
 	}
 }
 
-static void dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
 {
 	*((u32*)dt->dt.next) = value;
 	dt->dt.next += sizeof(u32);
@@ -765,7 +765,7 @@ static void dt_push_u32(struct iseries_f
 }
 
 #ifdef notyet
-static void dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
 {
 	*((u64*)dt->dt.next) = value;
 	dt->dt.next += sizeof(u64);
@@ -774,7 +774,7 @@ static void dt_push_u64(struct iseries_f
 }
 #endif
 
-static unsigned long dt_push_bytes(struct blob *blob, char *data, int len)
+static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
 {
 	unsigned long start = blob->next - (unsigned long)blob->data;
 
@@ -786,7 +786,7 @@ static unsigned long dt_push_bytes(struc
 	return start;
 }
 
-static void dt_start_node(struct iseries_flat_dt *dt, char *name)
+static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
 {
 	dt_push_u32(dt, OF_DT_BEGIN_NODE);
 	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
@@ -794,7 +794,8 @@ static void dt_start_node(struct iseries
 
 #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
 
-static void dt_prop(struct iseries_flat_dt *dt, char *name, char *data, int len)
+static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
+		char *data, int len)
 {
 	unsigned long offset;
 
@@ -813,39 +814,42 @@ static void dt_prop(struct iseries_flat_
 	dt_push_bytes(&dt->dt, data, len);
 }
 
-static void dt_prop_str(struct iseries_flat_dt *dt, char *name, char *data)
+static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
+		char *data)
 {
 	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
 }
 
-static void dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
 {
 	dt_prop(dt, name, (char *)&data, sizeof(u32));
 }
 
-static void dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
 {
 	dt_prop(dt, name, (char *)&data, sizeof(u64));
 }
 
-static void dt_prop_u64_list(struct iseries_flat_dt *dt, char *name, u64 *data, int n)
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
+		u64 *data, int n)
 {
 	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
 }
 
-static void dt_prop_u32_list(struct iseries_flat_dt *dt, char *name, u32 *data, int n)
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
+		u32 *data, int n)
 {
 	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
 }
 
 #ifdef notyet
-static void dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
 {
 	dt_prop(dt, name, NULL, 0);
 }
 #endif
 
-static void dt_cpus(struct iseries_flat_dt *dt)
+static void __init dt_cpus(struct iseries_flat_dt *dt)
 {
 	unsigned char buf[32];
 	unsigned char *p;
@@ -899,7 +903,7 @@ static void dt_cpus(struct iseries_flat_
 	dt_end_node(dt);
 }
 
-static void dt_model(struct iseries_flat_dt *dt)
+static void __init dt_model(struct iseries_flat_dt *dt)
 {
 	char buf[16] = "IBM,";
 
@@ -917,7 +921,7 @@ static void dt_model(struct iseries_flat
 	dt_prop_str(dt, "compatible", "IBM,iSeries");
 }
 
-static void dt_vdevices(struct iseries_flat_dt *dt)
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
 {
 	u32 reg = 0;
 	HvLpIndexMap vlan_map;
@@ -1006,11 +1010,32 @@ static void dt_vdevices(struct iseries_f
 	dt_end_node(dt);
 }
 
+struct pci_class_name {
+	u16 code;
+	char *name;
+	char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+	struct pci_class_name *cp;
+
+	for (cp = pci_class_name;
+			cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+		if (cp->code == class_code)
+			return cp;
+	return NULL;
+}
+
 /*
  * This assumes that the node slot is always on the primary bus!
  */
-static void scan_bridge_slot(struct iseries_flat_dt *dt, HvBusNumber bus,
-		struct HvCallPci_BridgeInfo *bridge_info)
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+		HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
 {
 	HvSubBusNumber sub_bus = bridge_info->subBusNumber;
 	u16 vendor_id;
@@ -1022,14 +1047,14 @@ static void scan_bridge_slot(struct iser
 	int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
 	int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
 	HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+	u8 devfn;
+	struct pci_class_name *cp;
 
 	/*
 	 * Connect all functions of any device found.
 	 */
 	for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
 		for (function = 0; function < 8; function++) {
-			u8 devfn;
-
 			HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
 					function);
 			err = HvCallXm_connectBusUnit(bus, sub_bus,
@@ -1070,12 +1095,20 @@ static void scan_bridge_slot(struct iser
 
 			devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
 					function);
-			if (function == 0)
-				snprintf(buf, sizeof(buf), "pci@%x",
-						PCI_SLOT(devfn));
+			cp = dt_find_pci_class_name(class_id >> 16);
+			if (cp && cp->name)
+				strncpy(buf, cp->name, sizeof(buf) - 1);
 			else
-				snprintf(buf, sizeof(buf), "pci@%x,%d",
-						PCI_SLOT(devfn), function);
+				snprintf(buf, sizeof(buf), "pci%x,%x",
+						vendor_id, device_id);
+			buf[sizeof(buf) - 1] = '\0';
+			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+					"@%x", PCI_SLOT(devfn));
+			buf[sizeof(buf) - 1] = '\0';
+			if (function != 0)
+				snprintf(buf + strlen(buf),
+					sizeof(buf) - strlen(buf),
+					",%x", function);
 			dt_start_node(dt, buf);
 			reg[0] = (bus << 16) | (devfn << 8);
 			reg[1] = 0;
@@ -1083,6 +1116,9 @@ static void scan_bridge_slot(struct iser
 			reg[3] = 0;
 			reg[4] = 0;
 			dt_prop_u32_list(dt, "reg", reg, 5);
+			if (cp && (cp->type || cp->name))
+				dt_prop_str(dt, "device_type",
+					cp->type ? cp->type : cp->name);
 			dt_prop_u32(dt, "vendor-id", vendor_id);
 			dt_prop_u32(dt, "device-id", device_id);
 			dt_prop_u32(dt, "class-code", class_id >> 8);
@@ -1097,7 +1133,7 @@ static void scan_bridge_slot(struct iser
 	}
 }
 
-static void scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
 		HvSubBusNumber sub_bus, int id_sel)
 {
 	struct HvCallPci_BridgeInfo bridge_info;
@@ -1139,7 +1175,7 @@ static void scan_bridge(struct iseries_f
 	}
 }
 
-static void scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
 {
 	struct HvCallPci_DeviceInfo dev_info;
 	const HvSubBusNumber sub_bus = 0;	/* EADs is always 0. */
@@ -1171,7 +1207,7 @@ static void scan_phb(struct iseries_flat
 	}
 }
 
-static void dt_pci_devices(struct iseries_flat_dt *dt)
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
 {
 	HvBusNumber bus;
 	char buf[32];
@@ -1207,7 +1243,8 @@ static void dt_pci_devices(struct iserie
 	}
 }
 
-static void build_flat_dt(struct iseries_flat_dt *dt, unsigned long phys_mem_size)
+static void __init build_flat_dt(struct iseries_flat_dt *dt,
+		unsigned long phys_mem_size)
 {
 	u64 tmp[2];
 
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (8 preceding siblings ...)
  2006-05-19  6:58 ` [PATCH 10/14] powerpc: give iSeries device tree nodes better names Stephen Rothwell
@ 2006-05-19  7:00 ` Stephen Rothwell
  2006-05-19  7:04 ` [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2 Stephen Rothwell
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  7:00 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev


Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/Makefile |    2 
 arch/powerpc/platforms/iseries/dt.c     |  618 +++++++++++++++++++++++++++++++
 arch/powerpc/platforms/iseries/setup.c  |  578 -----------------------------
 arch/powerpc/platforms/iseries/setup.h  |    2 
 4 files changed, 622 insertions(+), 578 deletions(-)
 create mode 100644 arch/powerpc/platforms/iseries/dt.c

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

5909be4784e723a8a0444a556801cb320a4ddffc
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 7e67a20..3230621 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,6 +1,6 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o mf.o lpevents.o \
+obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
 	hvcall.o proc.o htab.o iommu.o misc.o irq.o
 obj-$(CONFIG_PCI) += pci.o vpdinfo.o
 obj-$(CONFIG_SMP) += smp.o
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
new file mode 100644
index 0000000..93d4233
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -0,0 +1,618 @@
+/*
+ *    Copyright (c) 2005-2006 Michael Ellerman, IBM Corporation
+ *
+ *    Description:
+ *      This file contains all the routines to build a flattened device
+ *      tree for a legacy iSeries machine.
+ *
+ *      This program is free software; you can redistribute it and/or
+ *      modify it under the terms of the GNU General Public License
+ *      as published by the Free Software Foundation; either version
+ *      2 of the License, or (at your option) any later version.
+ */
+
+#undef DEBUG
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/pci_ids.h>
+#include <linux/threads.h>
+#include <linux/bitops.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/if_ether.h>	/* ETH_ALEN */
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/lppaca.h>
+#include <asm/page.h>
+#include <asm/cputable.h>
+#include <asm/abs_addr.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_config.h>
+#include <asm/iseries/hv_call_xm.h>
+#include <asm/iseries/it_exp_vpd_panel.h>
+#include <asm/udbg.h>
+
+#include "processor_vpd.h"
+#include "call_hpt.h"
+#include "call_pci.h"
+#include "pci.h"
+
+#ifdef DEBUG
+#define DBG(fmt...) udbg_printf(fmt)
+#else
+#define DBG(fmt...)
+#endif
+
+struct blob {
+	unsigned char data[PAGE_SIZE * 2];
+	unsigned long next;
+};
+
+struct iseries_flat_dt {
+	struct boot_param_header header;
+	u64 reserve_map[2];
+	struct blob dt;
+	struct blob strings;
+};
+
+static struct iseries_flat_dt iseries_dt;
+
+static void __init dt_init(struct iseries_flat_dt *dt)
+{
+	dt->header.off_mem_rsvmap =
+		offsetof(struct iseries_flat_dt, reserve_map);
+	dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
+	dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
+	dt->header.totalsize = sizeof(struct iseries_flat_dt);
+	dt->header.dt_strings_size = sizeof(struct blob);
+
+	/* There is no notion of hardware cpu id on iSeries */
+	dt->header.boot_cpuid_phys = smp_processor_id();
+
+	dt->dt.next = (unsigned long)&dt->dt.data;
+	dt->strings.next = (unsigned long)&dt->strings.data;
+
+	dt->header.magic = OF_DT_HEADER;
+	dt->header.version = 0x10;
+	dt->header.last_comp_version = 0x10;
+
+	dt->reserve_map[0] = 0;
+	dt->reserve_map[1] = 0;
+}
+
+static void __init dt_check_blob(struct blob *b)
+{
+	if (b->next >= (unsigned long)&b->next) {
+		DBG("Ran out of space in flat device tree blob!\n");
+		BUG();
+	}
+}
+
+static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
+{
+	*((u32*)dt->dt.next) = value;
+	dt->dt.next += sizeof(u32);
+
+	dt_check_blob(&dt->dt);
+}
+
+#ifdef notyet
+static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
+{
+	*((u64*)dt->dt.next) = value;
+	dt->dt.next += sizeof(u64);
+
+	dt_check_blob(&dt->dt);
+}
+#endif
+
+static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
+{
+	unsigned long start = blob->next - (unsigned long)blob->data;
+
+	memcpy((char *)blob->next, data, len);
+	blob->next = _ALIGN(blob->next + len, 4);
+
+	dt_check_blob(blob);
+
+	return start;
+}
+
+static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
+{
+	dt_push_u32(dt, OF_DT_BEGIN_NODE);
+	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
+}
+
+#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
+
+static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
+		char *data, int len)
+{
+	unsigned long offset;
+
+	dt_push_u32(dt, OF_DT_PROP);
+
+	/* Length of the data */
+	dt_push_u32(dt, len);
+
+	/* Put the property name in the string blob. */
+	offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
+
+	/* The offset of the properties name in the string blob. */
+	dt_push_u32(dt, (u32)offset);
+
+	/* The actual data. */
+	dt_push_bytes(&dt->dt, data, len);
+}
+
+static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
+		char *data)
+{
+	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
+}
+
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+{
+	dt_prop(dt, name, (char *)&data, sizeof(u32));
+}
+
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+{
+	dt_prop(dt, name, (char *)&data, sizeof(u64));
+}
+
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
+		u64 *data, int n)
+{
+	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
+}
+
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
+		u32 *data, int n)
+{
+	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
+}
+
+#ifdef notyet
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+{
+	dt_prop(dt, name, NULL, 0);
+}
+#endif
+
+static void __init dt_cpus(struct iseries_flat_dt *dt)
+{
+	unsigned char buf[32];
+	unsigned char *p;
+	unsigned int i, index;
+	struct IoHriProcessorVpd *d;
+	u32 pft_size[2];
+
+	/* yuck */
+	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
+	p = strchr(buf, ' ');
+	if (!p) p = buf + strlen(buf);
+
+	dt_start_node(dt, "cpus");
+	dt_prop_u32(dt, "#address-cells", 1);
+	dt_prop_u32(dt, "#size-cells", 0);
+
+	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
+	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
+
+	for (i = 0; i < NR_CPUS; i++) {
+		if (lppaca[i].dyn_proc_status >= 2)
+			continue;
+
+		snprintf(p, 32 - (p - buf), "@%d", i);
+		dt_start_node(dt, buf);
+
+		dt_prop_str(dt, "device_type", "cpu");
+
+		index = lppaca[i].dyn_hv_phys_proc_index;
+		d = &xIoHriProcessorVpd[index];
+
+		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
+		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
+
+		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
+		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
+
+		/* magic conversions to Hz copied from old code */
+		dt_prop_u32(dt, "clock-frequency",
+			((1UL << 34) * 1000000) / d->xProcFreq);
+		dt_prop_u32(dt, "timebase-frequency",
+			((1UL << 32) * 1000000) / d->xTimeBaseFreq);
+
+		dt_prop_u32(dt, "reg", i);
+
+		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
+
+		dt_end_node(dt);
+	}
+
+	dt_end_node(dt);
+}
+
+static void __init dt_model(struct iseries_flat_dt *dt)
+{
+	char buf[16] = "IBM,";
+
+	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
+	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
+	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
+	buf[11] = '\0';
+	dt_prop_str(dt, "system-id", buf);
+
+	/* "IBM," + machineType[0:4] */
+	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
+	buf[8] = '\0';
+	dt_prop_str(dt, "model", buf);
+
+	dt_prop_str(dt, "compatible", "IBM,iSeries");
+}
+
+static void __init dt_vdevices(struct iseries_flat_dt *dt)
+{
+	u32 reg = 0;
+	HvLpIndexMap vlan_map;
+	int i;
+	char buf[32];
+
+	dt_start_node(dt, "vdevice");
+	dt_prop_str(dt, "device_type", "vdevice");
+	dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
+	dt_prop_u32(dt, "#address-cells", 1);
+	dt_prop_u32(dt, "#size-cells", 0);
+
+	snprintf(buf, sizeof(buf), "vty@%08x", reg);
+	dt_start_node(dt, buf);
+	dt_prop_str(dt, "device_type", "serial");
+	dt_prop_u32(dt, "reg", reg);
+	dt_end_node(dt);
+	reg++;
+
+	snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
+	dt_start_node(dt, buf);
+	dt_prop_str(dt, "device_type", "vscsi");
+	dt_prop_str(dt, "compatible", "IBM,v-scsi");
+	dt_prop_u32(dt, "reg", reg);
+	dt_end_node(dt);
+	reg++;
+
+	vlan_map = HvLpConfig_getVirtualLanIndexMap();
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
+		unsigned char mac_addr[ETH_ALEN];
+
+		if ((vlan_map & (0x8000 >> i)) == 0)
+			continue;
+		snprintf(buf, 32, "l-lan@%08x", reg + i);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", "network");
+		dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan");
+		dt_prop_u32(dt, "reg", reg + i);
+		dt_prop_u32(dt, "linux,unit_address", i);
+
+		mac_addr[0] = 0x02;
+		mac_addr[1] = 0x01;
+		mac_addr[2] = 0xff;
+		mac_addr[3] = i;
+		mac_addr[4] = 0xff;
+		mac_addr[5] = HvLpConfig_getLpIndex_outline();
+		dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
+		dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
+		dt_prop_u32(dt, "max-frame-size", 9000);
+		dt_prop_u32(dt, "address-bits", 48);
+
+		dt_end_node(dt);
+	}
+	reg += HVMAXARCHITECTEDVIRTUALLANS;
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
+		snprintf(buf, 32, "viodasd@%08x", reg + i);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", "block");
+		dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd");
+		dt_prop_u32(dt, "reg", reg + i);
+		dt_prop_u32(dt, "linux,unit_address", i);
+		dt_end_node(dt);
+	}
+	reg += HVMAXARCHITECTEDVIRTUALDISKS;
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
+		snprintf(buf, 32, "viocd@%08x", reg + i);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", "block");
+		dt_prop_str(dt, "compatible", "IBM,iSeries-viocd");
+		dt_prop_u32(dt, "reg", reg + i);
+		dt_prop_u32(dt, "linux,unit_address", i);
+		dt_end_node(dt);
+	}
+	reg += HVMAXARCHITECTEDVIRTUALCDROMS;
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
+		snprintf(buf, 32, "viotape@%08x", reg + i);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", "byte");
+		dt_prop_str(dt, "compatible", "IBM,iSeries-viotape");
+		dt_prop_u32(dt, "reg", reg + i);
+		dt_prop_u32(dt, "linux,unit_address", i);
+		dt_end_node(dt);
+	}
+
+	dt_end_node(dt);
+}
+
+struct pci_class_name {
+	u16 code;
+	char *name;
+	char *type;
+};
+
+static struct pci_class_name __initdata pci_class_name[] = {
+	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
+};
+
+static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
+{
+	struct pci_class_name *cp;
+
+	for (cp = pci_class_name;
+			cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
+		if (cp->code == class_code)
+			return cp;
+	return NULL;
+}
+
+/*
+ * This assumes that the node slot is always on the primary bus!
+ */
+static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
+		HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
+{
+	HvSubBusNumber sub_bus = bridge_info->subBusNumber;
+	u16 vendor_id;
+	u16 device_id;
+	u32 class_id;
+	int err;
+	char buf[32];
+	u32 reg[5];
+	int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
+	int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
+	HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
+	u8 devfn;
+	struct pci_class_name *cp;
+
+	/*
+	 * Connect all functions of any device found.
+	 */
+	for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
+		for (function = 0; function < 8; function++) {
+			HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
+					function);
+			err = HvCallXm_connectBusUnit(bus, sub_bus,
+					agent_id, 0);
+			if (err) {
+				if (err != 0x302)
+					printk(KERN_DEBUG
+						"connectBusUnit(%x, %x, %x) "
+						"== %x\n",
+						bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_VENDOR_ID, &vendor_id);
+			if (err) {
+				printk(KERN_DEBUG
+					"ReadVendor(%x, %x, %x) == %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
+					PCI_DEVICE_ID, &device_id);
+			if (err) {
+				printk(KERN_DEBUG
+					"ReadDevice(%x, %x, %x) == %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+			err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
+					PCI_CLASS_REVISION , &class_id);
+			if (err) {
+				printk(KERN_DEBUG
+					"ReadClass(%x, %x, %x) == %x\n",
+					bus, sub_bus, agent_id, err);
+				continue;
+			}
+
+			devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
+					function);
+			cp = dt_find_pci_class_name(class_id >> 16);
+			if (cp && cp->name)
+				strncpy(buf, cp->name, sizeof(buf) - 1);
+			else
+				snprintf(buf, sizeof(buf), "pci%x,%x",
+						vendor_id, device_id);
+			buf[sizeof(buf) - 1] = '\0';
+			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+					"@%x", PCI_SLOT(devfn));
+			buf[sizeof(buf) - 1] = '\0';
+			if (function != 0)
+				snprintf(buf + strlen(buf),
+					sizeof(buf) - strlen(buf),
+					",%x", function);
+			dt_start_node(dt, buf);
+			reg[0] = (bus << 16) | (devfn << 8);
+			reg[1] = 0;
+			reg[2] = 0;
+			reg[3] = 0;
+			reg[4] = 0;
+			dt_prop_u32_list(dt, "reg", reg, 5);
+			if (cp && (cp->type || cp->name))
+				dt_prop_str(dt, "device_type",
+					cp->type ? cp->type : cp->name);
+			dt_prop_u32(dt, "vendor-id", vendor_id);
+			dt_prop_u32(dt, "device-id", device_id);
+			dt_prop_u32(dt, "class-code", class_id >> 8);
+			dt_prop_u32(dt, "revision-id", class_id & 0xff);
+			dt_prop_u32(dt, "linux,subbus", sub_bus);
+			dt_prop_u32(dt, "linux,agent-id", agent_id);
+			dt_prop_u32(dt, "linux,logical-slot-number",
+					bridge_info->logicalSlotNumber);
+			dt_end_node(dt);
+
+		}
+	}
+}
+
+static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
+		HvSubBusNumber sub_bus, int id_sel)
+{
+	struct HvCallPci_BridgeInfo bridge_info;
+	HvAgentId agent_id;
+	int function;
+	int ret;
+
+	/* Note: hvSubBus and irq is always be 0 at this level! */
+	for (function = 0; function < 8; ++function) {
+		agent_id = ISERIES_PCI_AGENTID(id_sel, function);
+		ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
+		if (ret != 0) {
+			if (ret != 0xb)
+				printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
+						"== %x\n",
+						bus, sub_bus, agent_id, ret);
+			continue;
+		}
+		printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+				bus, id_sel, function, agent_id);
+		ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
+				iseries_hv_addr(&bridge_info),
+				sizeof(struct HvCallPci_BridgeInfo));
+		if (ret != 0)
+			continue;
+		printk("bridge info: type %x subbus %x "
+			"maxAgents %x maxsubbus %x logslot %x\n",
+			bridge_info.busUnitInfo.deviceType,
+			bridge_info.subBusNumber,
+			bridge_info.maxAgents,
+			bridge_info.maxSubBusNumber,
+			bridge_info.logicalSlotNumber);
+		if (bridge_info.busUnitInfo.deviceType ==
+				HvCallPci_BridgeDevice)
+			scan_bridge_slot(dt, bus, &bridge_info);
+		else
+			printk("PCI: Invalid Bridge Configuration(0x%02X)",
+				bridge_info.busUnitInfo.deviceType);
+	}
+}
+
+static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
+{
+	struct HvCallPci_DeviceInfo dev_info;
+	const HvSubBusNumber sub_bus = 0;	/* EADs is always 0. */
+	int err;
+	int id_sel;
+	const int max_agents = 8;
+
+	/*
+	 * Probe for EADs Bridges
+	 */
+	for (id_sel = 1; id_sel < max_agents; ++id_sel) {
+		err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
+				iseries_hv_addr(&dev_info),
+				sizeof(struct HvCallPci_DeviceInfo));
+		if (err) {
+			if (err != 0x302)
+				printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
+						"== %x\n",
+						bus, sub_bus, id_sel, err);
+			continue;
+		}
+		if (dev_info.deviceType != HvCallPci_NodeDevice) {
+			printk(KERN_DEBUG "PCI: Invalid System Configuration"
+					"(0x%02X) for bus 0x%02x id 0x%02x.\n",
+					dev_info.deviceType, bus, id_sel);
+			continue;
+		}
+		scan_bridge(dt, bus, sub_bus, id_sel);
+	}
+}
+
+static void __init dt_pci_devices(struct iseries_flat_dt *dt)
+{
+	HvBusNumber bus;
+	char buf[32];
+	u32 buses[2];
+	int phb_num = 0;
+
+	/* Check all possible buses. */
+	for (bus = 0; bus < 256; bus++) {
+		int err = HvCallXm_testBus(bus);
+
+		if (err) {
+			/*
+			 * Check for Unexpected Return code, a clue that
+			 * something has gone wrong.
+			 */
+			if (err != 0x0301)
+				printk(KERN_ERR "Unexpected Return on Probe"
+						"(0x%02X): 0x%04X", bus, err);
+			continue;
+		}
+		printk("bus %d appears to exist\n", bus);
+		snprintf(buf, 32, "pci@%d", phb_num);
+		dt_start_node(dt, buf);
+		dt_prop_str(dt, "device_type", "pci");
+		dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
+		dt_prop_u32(dt, "#address-cells", 3);
+		dt_prop_u32(dt, "#size-cells", 2);
+		buses[0] = buses[1] = bus;
+		dt_prop_u32_list(dt, "bus-range", buses, 2);
+		scan_phb(dt, bus);
+		dt_end_node(dt);
+		phb_num++;
+	}
+}
+
+void * __init build_flat_dt(unsigned long phys_mem_size)
+{
+	u64 tmp[2];
+
+	dt_init(&iseries_dt);
+
+	dt_start_node(&iseries_dt, "");
+
+	dt_prop_u32(&iseries_dt, "#address-cells", 2);
+	dt_prop_u32(&iseries_dt, "#size-cells", 2);
+	dt_model(&iseries_dt);
+
+	/* /memory */
+	dt_start_node(&iseries_dt, "memory@0");
+	dt_prop_str(&iseries_dt, "name", "memory");
+	dt_prop_str(&iseries_dt, "device_type", "memory");
+	tmp[0] = 0;
+	tmp[1] = phys_mem_size;
+	dt_prop_u64_list(&iseries_dt, "reg", tmp, 2);
+	dt_end_node(&iseries_dt);
+
+	/* /chosen */
+	dt_start_node(&iseries_dt, "chosen");
+	dt_prop_str(&iseries_dt, "bootargs", cmd_line);
+	dt_end_node(&iseries_dt);
+
+	dt_cpus(&iseries_dt);
+
+	dt_vdevices(&iseries_dt);
+	dt_pci_devices(&iseries_dt);
+
+	dt_end_node(&iseries_dt);
+
+	dt_push_u32(&iseries_dt, OF_DT_END);
+
+	return &iseries_dt;
+}
diff --git a/arch/powerpc/platforms/iseries/setup.c b/arch/powerpc/platforms/iseries/setup.c
index 5661bd0..617c724 100644
--- a/arch/powerpc/platforms/iseries/setup.c
+++ b/arch/powerpc/platforms/iseries/setup.c
@@ -28,7 +28,6 @@ #include <linux/kdev_t.h>
 #include <linux/major.h>
 #include <linux/root_dev.h>
 #include <linux/kernel.h>
-#include <linux/if_ether.h>	/* ETH_ALEN */
 
 #include <asm/processor.h>
 #include <asm/machdep.h>
@@ -46,13 +45,11 @@ #include <asm/paca.h>
 #include <asm/cache.h>
 #include <asm/sections.h>
 #include <asm/abs_addr.h>
-#include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_lp_config.h>
 #include <asm/iseries/hv_call_event.h>
 #include <asm/iseries/hv_call_xm.h>
 #include <asm/iseries/it_lp_queue.h>
 #include <asm/iseries/mf.h>
-#include <asm/iseries/it_exp_vpd_panel.h>
 #include <asm/iseries/hv_lp_event.h>
 #include <asm/iseries/lpar_map.h>
 #include <asm/udbg.h>
@@ -66,8 +63,6 @@ #include "processor_vpd.h"
 #include "main_store.h"
 #include "call_sm.h"
 #include "call_hpt.h"
-#include "call_pci.h"
-#include "pci.h"
 
 #ifdef DEBUG
 #define DBG(fmt...) udbg_printf(fmt)
@@ -711,575 +706,6 @@ define_machine(iseries) {
 	/* XXX Implement enable_pmcs for iSeries */
 };
 
-struct blob {
-	unsigned char data[PAGE_SIZE * 2];
-	unsigned long next;
-};
-
-struct iseries_flat_dt {
-	struct boot_param_header header;
-	u64 reserve_map[2];
-	struct blob dt;
-	struct blob strings;
-};
-
-static struct iseries_flat_dt iseries_dt;
-
-static void __init dt_init(struct iseries_flat_dt *dt)
-{
-	dt->header.off_mem_rsvmap =
-		offsetof(struct iseries_flat_dt, reserve_map);
-	dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
-	dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
-	dt->header.totalsize = sizeof(struct iseries_flat_dt);
-	dt->header.dt_strings_size = sizeof(struct blob);
-
-	/* There is no notion of hardware cpu id on iSeries */
-	dt->header.boot_cpuid_phys = smp_processor_id();
-
-	dt->dt.next = (unsigned long)&dt->dt.data;
-	dt->strings.next = (unsigned long)&dt->strings.data;
-
-	dt->header.magic = OF_DT_HEADER;
-	dt->header.version = 0x10;
-	dt->header.last_comp_version = 0x10;
-
-	dt->reserve_map[0] = 0;
-	dt->reserve_map[1] = 0;
-}
-
-static void __init dt_check_blob(struct blob *b)
-{
-	if (b->next >= (unsigned long)&b->next) {
-		DBG("Ran out of space in flat device tree blob!\n");
-		BUG();
-	}
-}
-
-static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
-{
-	*((u32*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u32);
-
-	dt_check_blob(&dt->dt);
-}
-
-#ifdef notyet
-static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
-{
-	*((u64*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u64);
-
-	dt_check_blob(&dt->dt);
-}
-#endif
-
-static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
-{
-	unsigned long start = blob->next - (unsigned long)blob->data;
-
-	memcpy((char *)blob->next, data, len);
-	blob->next = _ALIGN(blob->next + len, 4);
-
-	dt_check_blob(blob);
-
-	return start;
-}
-
-static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
-{
-	dt_push_u32(dt, OF_DT_BEGIN_NODE);
-	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
-}
-
-#define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
-
-static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
-		char *data, int len)
-{
-	unsigned long offset;
-
-	dt_push_u32(dt, OF_DT_PROP);
-
-	/* Length of the data */
-	dt_push_u32(dt, len);
-
-	/* Put the property name in the string blob. */
-	offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
-
-	/* The offset of the properties name in the string blob. */
-	dt_push_u32(dt, (u32)offset);
-
-	/* The actual data. */
-	dt_push_bytes(&dt->dt, data, len);
-}
-
-static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
-		char *data)
-{
-	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
-}
-
-static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
-{
-	dt_prop(dt, name, (char *)&data, sizeof(u32));
-}
-
-static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
-{
-	dt_prop(dt, name, (char *)&data, sizeof(u64));
-}
-
-static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
-		u64 *data, int n)
-{
-	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
-}
-
-static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
-		u32 *data, int n)
-{
-	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
-}
-
-#ifdef notyet
-static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
-{
-	dt_prop(dt, name, NULL, 0);
-}
-#endif
-
-static void __init dt_cpus(struct iseries_flat_dt *dt)
-{
-	unsigned char buf[32];
-	unsigned char *p;
-	unsigned int i, index;
-	struct IoHriProcessorVpd *d;
-	u32 pft_size[2];
-
-	/* yuck */
-	snprintf(buf, 32, "PowerPC,%s", cur_cpu_spec->cpu_name);
-	p = strchr(buf, ' ');
-	if (!p) p = buf + strlen(buf);
-
-	dt_start_node(dt, "cpus");
-	dt_prop_u32(dt, "#address-cells", 1);
-	dt_prop_u32(dt, "#size-cells", 0);
-
-	pft_size[0] = 0; /* NUMA CEC cookie, 0 for non NUMA  */
-	pft_size[1] = __ilog2(HvCallHpt_getHptPages() * HW_PAGE_SIZE);
-
-	for (i = 0; i < NR_CPUS; i++) {
-		if (lppaca[i].dyn_proc_status >= 2)
-			continue;
-
-		snprintf(p, 32 - (p - buf), "@%d", i);
-		dt_start_node(dt, buf);
-
-		dt_prop_str(dt, "device_type", "cpu");
-
-		index = lppaca[i].dyn_hv_phys_proc_index;
-		d = &xIoHriProcessorVpd[index];
-
-		dt_prop_u32(dt, "i-cache-size", d->xInstCacheSize * 1024);
-		dt_prop_u32(dt, "i-cache-line-size", d->xInstCacheOperandSize);
-
-		dt_prop_u32(dt, "d-cache-size", d->xDataL1CacheSizeKB * 1024);
-		dt_prop_u32(dt, "d-cache-line-size", d->xDataCacheOperandSize);
-
-		/* magic conversions to Hz copied from old code */
-		dt_prop_u32(dt, "clock-frequency",
-			((1UL << 34) * 1000000) / d->xProcFreq);
-		dt_prop_u32(dt, "timebase-frequency",
-			((1UL << 32) * 1000000) / d->xTimeBaseFreq);
-
-		dt_prop_u32(dt, "reg", i);
-
-		dt_prop_u32_list(dt, "ibm,pft-size", pft_size, 2);
-
-		dt_end_node(dt);
-	}
-
-	dt_end_node(dt);
-}
-
-static void __init dt_model(struct iseries_flat_dt *dt)
-{
-	char buf[16] = "IBM,";
-
-	/* "IBM," + mfgId[2:3] + systemSerial[1:5] */
-	strne2a(buf + 4, xItExtVpdPanel.mfgID + 2, 2);
-	strne2a(buf + 6, xItExtVpdPanel.systemSerial + 1, 5);
-	buf[11] = '\0';
-	dt_prop_str(dt, "system-id", buf);
-
-	/* "IBM," + machineType[0:4] */
-	strne2a(buf + 4, xItExtVpdPanel.machineType, 4);
-	buf[8] = '\0';
-	dt_prop_str(dt, "model", buf);
-
-	dt_prop_str(dt, "compatible", "IBM,iSeries");
-}
-
-static void __init dt_vdevices(struct iseries_flat_dt *dt)
-{
-	u32 reg = 0;
-	HvLpIndexMap vlan_map;
-	int i;
-	char buf[32];
-
-	dt_start_node(dt, "vdevice");
-	dt_prop_str(dt, "device_type", "vdevice");
-	dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
-	dt_prop_u32(dt, "#address-cells", 1);
-	dt_prop_u32(dt, "#size-cells", 0);
-
-	snprintf(buf, sizeof(buf), "vty@%08x", reg);
-	dt_start_node(dt, buf);
-	dt_prop_str(dt, "device_type", "serial");
-	dt_prop_u32(dt, "reg", reg);
-	dt_end_node(dt);
-	reg++;
-
-	snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
-	dt_start_node(dt, buf);
-	dt_prop_str(dt, "device_type", "vscsi");
-	dt_prop_str(dt, "compatible", "IBM,v-scsi");
-	dt_prop_u32(dt, "reg", reg);
-	dt_end_node(dt);
-	reg++;
-
-	vlan_map = HvLpConfig_getVirtualLanIndexMap();
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALLANS; i++) {
-		unsigned char mac_addr[ETH_ALEN];
-
-		if ((vlan_map & (0x8000 >> i)) == 0)
-			continue;
-		snprintf(buf, 32, "l-lan@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "network");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-
-		mac_addr[0] = 0x02;
-		mac_addr[1] = 0x01;
-		mac_addr[2] = 0xff;
-		mac_addr[3] = i;
-		mac_addr[4] = 0xff;
-		mac_addr[5] = HvLpConfig_getLpIndex_outline();
-		dt_prop(dt, "local-mac-address", (char *)mac_addr, ETH_ALEN);
-		dt_prop(dt, "mac-address", (char *)mac_addr, ETH_ALEN);
-		dt_prop_u32(dt, "max-frame-size", 9000);
-		dt_prop_u32(dt, "address-bits", 48);
-
-		dt_end_node(dt);
-	}
-	reg += HVMAXARCHITECTEDVIRTUALLANS;
-
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
-		snprintf(buf, 32, "viodasd@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "block");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-		dt_end_node(dt);
-	}
-	reg += HVMAXARCHITECTEDVIRTUALDISKS;
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
-		snprintf(buf, 32, "viocd@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "block");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-viocd");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-		dt_end_node(dt);
-	}
-	reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
-		snprintf(buf, 32, "viotape@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "byte");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-viotape");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-		dt_end_node(dt);
-	}
-
-	dt_end_node(dt);
-}
-
-struct pci_class_name {
-	u16 code;
-	char *name;
-	char *type;
-};
-
-static struct pci_class_name __initdata pci_class_name[] = {
-	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
-};
-
-static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
-{
-	struct pci_class_name *cp;
-
-	for (cp = pci_class_name;
-			cp < &pci_class_name[ARRAY_SIZE(pci_class_name)]; cp++)
-		if (cp->code == class_code)
-			return cp;
-	return NULL;
-}
-
-/*
- * This assumes that the node slot is always on the primary bus!
- */
-static void __init scan_bridge_slot(struct iseries_flat_dt *dt,
-		HvBusNumber bus, struct HvCallPci_BridgeInfo *bridge_info)
-{
-	HvSubBusNumber sub_bus = bridge_info->subBusNumber;
-	u16 vendor_id;
-	u16 device_id;
-	u32 class_id;
-	int err;
-	char buf[32];
-	u32 reg[5];
-	int id_sel = ISERIES_GET_DEVICE_FROM_SUBBUS(sub_bus);
-	int function = ISERIES_GET_FUNCTION_FROM_SUBBUS(sub_bus);
-	HvAgentId eads_id_sel = ISERIES_PCI_AGENTID(id_sel, function);
-	u8 devfn;
-	struct pci_class_name *cp;
-
-	/*
-	 * Connect all functions of any device found.
-	 */
-	for (id_sel = 1; id_sel <= bridge_info->maxAgents; id_sel++) {
-		for (function = 0; function < 8; function++) {
-			HvAgentId agent_id = ISERIES_PCI_AGENTID(id_sel,
-					function);
-			err = HvCallXm_connectBusUnit(bus, sub_bus,
-					agent_id, 0);
-			if (err) {
-				if (err != 0x302)
-					printk(KERN_DEBUG
-						"connectBusUnit(%x, %x, %x) "
-						"== %x\n",
-						bus, sub_bus, agent_id, err);
-				continue;
-			}
-
-			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
-					PCI_VENDOR_ID, &vendor_id);
-			if (err) {
-				printk(KERN_DEBUG
-					"ReadVendor(%x, %x, %x) == %x\n",
-					bus, sub_bus, agent_id, err);
-				continue;
-			}
-			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
-					PCI_DEVICE_ID, &device_id);
-			if (err) {
-				printk(KERN_DEBUG
-					"ReadDevice(%x, %x, %x) == %x\n",
-					bus, sub_bus, agent_id, err);
-				continue;
-			}
-			err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
-					PCI_CLASS_REVISION , &class_id);
-			if (err) {
-				printk(KERN_DEBUG
-					"ReadClass(%x, %x, %x) == %x\n",
-					bus, sub_bus, agent_id, err);
-				continue;
-			}
-
-			devfn = PCI_DEVFN(ISERIES_ENCODE_DEVICE(eads_id_sel),
-					function);
-			cp = dt_find_pci_class_name(class_id >> 16);
-			if (cp && cp->name)
-				strncpy(buf, cp->name, sizeof(buf) - 1);
-			else
-				snprintf(buf, sizeof(buf), "pci%x,%x",
-						vendor_id, device_id);
-			buf[sizeof(buf) - 1] = '\0';
-			snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-					"@%x", PCI_SLOT(devfn));
-			buf[sizeof(buf) - 1] = '\0';
-			if (function != 0)
-				snprintf(buf + strlen(buf),
-					sizeof(buf) - strlen(buf),
-					",%x", function);
-			dt_start_node(dt, buf);
-			reg[0] = (bus << 16) | (devfn << 8);
-			reg[1] = 0;
-			reg[2] = 0;
-			reg[3] = 0;
-			reg[4] = 0;
-			dt_prop_u32_list(dt, "reg", reg, 5);
-			if (cp && (cp->type || cp->name))
-				dt_prop_str(dt, "device_type",
-					cp->type ? cp->type : cp->name);
-			dt_prop_u32(dt, "vendor-id", vendor_id);
-			dt_prop_u32(dt, "device-id", device_id);
-			dt_prop_u32(dt, "class-code", class_id >> 8);
-			dt_prop_u32(dt, "revision-id", class_id & 0xff);
-			dt_prop_u32(dt, "linux,subbus", sub_bus);
-			dt_prop_u32(dt, "linux,agent-id", agent_id);
-			dt_prop_u32(dt, "linux,logical-slot-number",
-					bridge_info->logicalSlotNumber);
-			dt_end_node(dt);
-
-		}
-	}
-}
-
-static void __init scan_bridge(struct iseries_flat_dt *dt, HvBusNumber bus,
-		HvSubBusNumber sub_bus, int id_sel)
-{
-	struct HvCallPci_BridgeInfo bridge_info;
-	HvAgentId agent_id;
-	int function;
-	int ret;
-
-	/* Note: hvSubBus and irq is always be 0 at this level! */
-	for (function = 0; function < 8; ++function) {
-		agent_id = ISERIES_PCI_AGENTID(id_sel, function);
-		ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
-		if (ret != 0) {
-			if (ret != 0xb)
-				printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
-						"== %x\n",
-						bus, sub_bus, agent_id, ret);
-			continue;
-		}
-		printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
-				bus, id_sel, function, agent_id);
-		ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
-				iseries_hv_addr(&bridge_info),
-				sizeof(struct HvCallPci_BridgeInfo));
-		if (ret != 0)
-			continue;
-		printk("bridge info: type %x subbus %x "
-			"maxAgents %x maxsubbus %x logslot %x\n",
-			bridge_info.busUnitInfo.deviceType,
-			bridge_info.subBusNumber,
-			bridge_info.maxAgents,
-			bridge_info.maxSubBusNumber,
-			bridge_info.logicalSlotNumber);
-		if (bridge_info.busUnitInfo.deviceType ==
-				HvCallPci_BridgeDevice)
-			scan_bridge_slot(dt, bus, &bridge_info);
-		else
-			printk("PCI: Invalid Bridge Configuration(0x%02X)",
-				bridge_info.busUnitInfo.deviceType);
-	}
-}
-
-static void __init scan_phb(struct iseries_flat_dt *dt, HvBusNumber bus)
-{
-	struct HvCallPci_DeviceInfo dev_info;
-	const HvSubBusNumber sub_bus = 0;	/* EADs is always 0. */
-	int err;
-	int id_sel;
-	const int max_agents = 8;
-
-	/*
-	 * Probe for EADs Bridges
-	 */
-	for (id_sel = 1; id_sel < max_agents; ++id_sel) {
-		err = HvCallPci_getDeviceInfo(bus, sub_bus, id_sel,
-				iseries_hv_addr(&dev_info),
-				sizeof(struct HvCallPci_DeviceInfo));
-		if (err) {
-			if (err != 0x302)
-				printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
-						"== %x\n",
-						bus, sub_bus, id_sel, err);
-			continue;
-		}
-		if (dev_info.deviceType != HvCallPci_NodeDevice) {
-			printk(KERN_DEBUG "PCI: Invalid System Configuration"
-					"(0x%02X) for bus 0x%02x id 0x%02x.\n",
-					dev_info.deviceType, bus, id_sel);
-			continue;
-		}
-		scan_bridge(dt, bus, sub_bus, id_sel);
-	}
-}
-
-static void __init dt_pci_devices(struct iseries_flat_dt *dt)
-{
-	HvBusNumber bus;
-	char buf[32];
-	u32 buses[2];
-	int phb_num = 0;
-
-	/* Check all possible buses. */
-	for (bus = 0; bus < 256; bus++) {
-		int err = HvCallXm_testBus(bus);
-
-		if (err) {
-			/*
-			 * Check for Unexpected Return code, a clue that
-			 * something has gone wrong.
-			 */
-			if (err != 0x0301)
-				printk(KERN_ERR "Unexpected Return on Probe"
-						"(0x%02X): 0x%04X", bus, err);
-			continue;
-		}
-		printk("bus %d appears to exist\n", bus);
-		snprintf(buf, 32, "pci@%d", phb_num);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "pci");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
-		dt_prop_u32(dt, "#address-cells", 3);
-		dt_prop_u32(dt, "#size-cells", 2);
-		buses[0] = buses[1] = bus;
-		dt_prop_u32_list(dt, "bus-range", buses, 2);
-		scan_phb(dt, bus);
-		dt_end_node(dt);
-		phb_num++;
-	}
-}
-
-static void __init build_flat_dt(struct iseries_flat_dt *dt,
-		unsigned long phys_mem_size)
-{
-	u64 tmp[2];
-
-	dt_init(dt);
-
-	dt_start_node(dt, "");
-
-	dt_prop_u32(dt, "#address-cells", 2);
-	dt_prop_u32(dt, "#size-cells", 2);
-	dt_model(dt);
-
-	/* /memory */
-	dt_start_node(dt, "memory@0");
-	dt_prop_str(dt, "name", "memory");
-	dt_prop_str(dt, "device_type", "memory");
-	tmp[0] = 0;
-	tmp[1] = phys_mem_size;
-	dt_prop_u64_list(dt, "reg", tmp, 2);
-	dt_end_node(dt);
-
-	/* /chosen */
-	dt_start_node(dt, "chosen");
-	dt_prop_str(dt, "bootargs", cmd_line);
-	dt_end_node(dt);
-
-	dt_cpus(dt);
-
-	dt_vdevices(dt);
-	dt_pci_devices(dt);
-
-	dt_end_node(dt);
-
-	dt_push_u32(dt, OF_DT_END);
-}
-
 void * __init iSeries_early_setup(void)
 {
 	unsigned long phys_mem_size;
@@ -1294,9 +720,7 @@ void * __init iSeries_early_setup(void)
 
 	iSeries_get_cmdline();
 
-	build_flat_dt(&iseries_dt, phys_mem_size);
-
-	return (void *) __pa(&iseries_dt);
+	return (void *) __pa(build_flat_dt(phys_mem_size));
 }
 
 static void hvputc(char c)
diff --git a/arch/powerpc/platforms/iseries/setup.h b/arch/powerpc/platforms/iseries/setup.h
index 5213044..0a47ac5 100644
--- a/arch/powerpc/platforms/iseries/setup.h
+++ b/arch/powerpc/platforms/iseries/setup.h
@@ -21,4 +21,6 @@ extern unsigned long iSeries_get_boot_ti
 extern int iSeries_set_rtc_time(struct rtc_time *tm);
 extern void iSeries_get_rtc_time(struct rtc_time *tm);
 
+extern void *build_flat_dt(unsigned long phys_mem_size);
+
 #endif /* __ISERIES_SETUP_H__ */
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (9 preceding siblings ...)
  2006-05-19  7:00 ` [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c Stephen Rothwell
@ 2006-05-19  7:04 ` Stephen Rothwell
  2006-05-19  7:04 ` [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic Stephen Rothwell
  2006-05-19  7:06 ` [PATCH 14/14] powerpc: cleanup of iSeries flat device tree Stephen Rothwell
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  7:04 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

This actually simplies things as we just figure out how much space we
used at the end and adjust klimit then.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/dt.c |   62 +++++++++++------------------------
 1 files changed, 19 insertions(+), 43 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

0496bb52c33374b4f014df39c0e8a1b53325e93b
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 0371329..2a51ec1 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -27,7 +27,6 @@ #include <linux/if_ether.h>	/* ETH_ALEN 
 #include <asm/machdep.h>
 #include <asm/prom.h>
 #include <asm/lppaca.h>
-#include <asm/page.h>
 #include <asm/cputable.h>
 #include <asm/abs_addr.h>
 #include <asm/system.h>
@@ -51,15 +50,10 @@ #endif
 extern char __dt_strings_start[];
 extern char __dt_strings_end[];
 
-struct blob {
-	unsigned char data[PAGE_SIZE * 2];
-	unsigned long next;
-};
-
 struct iseries_flat_dt {
 	struct boot_param_header header;
 	u64 reserve_map[2];
-	struct blob *dt;
+	void *data;
 };
 
 static struct iseries_flat_dt *iseries_dt;
@@ -76,15 +70,12 @@ static struct iseries_flat_dt * __init d
 	dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
 	dt->header.off_dt_struct = dt->header.off_dt_strings
 		+ ALIGN(str_len, 8);
-	dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct);
-	klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8);
-	dt->header.totalsize = klimit - (unsigned long)dt;
+	dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
 	dt->header.dt_strings_size = str_len;
 
 	/* There is no notion of hardware cpu id on iSeries */
 	dt->header.boot_cpuid_phys = smp_processor_id();
 
-	dt->dt->next = (unsigned long)&dt->dt->data;
 	memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
 			str_len);
 
@@ -98,54 +89,37 @@ static struct iseries_flat_dt * __init d
 	return dt;
 }
 
-static void __init dt_check_blob(struct blob *b)
-{
-	if (b->next >= (unsigned long)&b->next) {
-		DBG("Ran out of space in flat device tree blob!\n");
-		BUG();
-	}
-}
-
 static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
 {
-	*((u32*)dt->dt->next) = value;
-	dt->dt->next += sizeof(u32);
-
-	dt_check_blob(dt->dt);
+	*((u32 *)dt->data) = value;
+	dt->data += sizeof(u32);
 }
 
 #ifdef notyet
 static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
 {
-	*((u64*)dt->dt->next) = value;
-	dt->dt->next += sizeof(u64);
-
-	dt_check_blob(dt->dt);
+	*((u64 *)dt->data) = value;
+	dt->data += sizeof(u64);
 }
 #endif
 
-static unsigned long __init dt_push_bytes(struct blob *blob, char *data, int len)
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data,
+		int len)
 {
-	unsigned long start = blob->next - (unsigned long)blob->data;
-
-	memcpy((char *)blob->next, data, len);
-	blob->next = _ALIGN(blob->next + len, 4);
-
-	dt_check_blob(blob);
-
-	return start;
+	memcpy(dt->data, data, len);
+	dt->data += ALIGN(len, 4);
 }
 
 static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
 {
 	dt_push_u32(dt, OF_DT_BEGIN_NODE);
-	dt_push_bytes(dt->dt, name, strlen(name) + 1);
+	dt_push_bytes(dt, name, strlen(name) + 1);
 }
 
 #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
 
 static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
-		char *data, int len)
+		void *data, int len)
 {
 	unsigned long offset;
 
@@ -160,7 +134,7 @@ static void __init dt_prop(struct iserie
 	dt_push_u32(dt, (u32)offset);
 
 	/* The actual data. */
-	dt_push_bytes(dt->dt, data, len);
+	dt_push_bytes(dt, data, len);
 }
 
 static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
@@ -171,24 +145,24 @@ static void __init dt_prop_str(struct is
 
 static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
 {
-	dt_prop(dt, name, (char *)&data, sizeof(u32));
+	dt_prop(dt, name, &data, sizeof(u32));
 }
 
 static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
 {
-	dt_prop(dt, name, (char *)&data, sizeof(u64));
+	dt_prop(dt, name, &data, sizeof(u64));
 }
 
 static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
 		u64 *data, int n)
 {
-	dt_prop(dt, name, (char *)data, sizeof(u64) * n);
+	dt_prop(dt, name, data, sizeof(u64) * n);
 }
 
 static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
 		u32 *data, int n)
 {
-	dt_prop(dt, name, (char *)data, sizeof(u32) * n);
+	dt_prop(dt, name, data, sizeof(u32) * n);
 }
 
 #ifdef notyet
@@ -595,6 +569,8 @@ static void __init dt_pci_devices(struct
 static void dt_finish(struct iseries_flat_dt *dt)
 {
 	dt_push_u32(dt, OF_DT_END);
+	dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt;
+	klimit = ALIGN((unsigned long)dt->data, 8);
 }
 
 void * __init build_flat_dt(unsigned long phys_mem_size)
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (10 preceding siblings ...)
  2006-05-19  7:04 ` [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2 Stephen Rothwell
@ 2006-05-19  7:04 ` Stephen Rothwell
  2006-05-19  7:06 ` [PATCH 14/14] powerpc: cleanup of iSeries flat device tree Stephen Rothwell
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  7:04 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

First we capture all the strings from dt.c statically by noting that gcc
puts them in a special section of their own.  Idea from Michael Ellerman.

Then we move the flattened device tree to klimit.

Still to come, making the values blob grow as needed.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/kernel/vmlinux.lds.S       |    5 ++
 arch/powerpc/platforms/iseries/Makefile |    5 +-
 arch/powerpc/platforms/iseries/dt.c     |   96 ++++++++++++++++++-------------
 3 files changed, 66 insertions(+), 40 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

0f75701d8ac409a5e5c9e1de1d414129a435b267
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index fe79c25..8b25953 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -93,6 +93,11 @@ #endif /* CONFIG_PPC32 */
 		__ptov_table_begin = .;
 		*(.ptov_fixup);
 		__ptov_table_end = .;
+#ifdef CONFIG_PPC_ISERIES
+		__dt_strings_start = .;
+		*(.dt_strings);
+		__dt_strings_end = .;
+#endif
 	}
 
 	. = ALIGN(16);
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 3230621..dee4eb4 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -1,8 +1,11 @@
 EXTRA_CFLAGS	+= -mno-minimal-toc
 
-obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt.o mf.o lpevents.o \
+obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
 	hvcall.o proc.o htab.o iommu.o misc.o irq.o
 obj-$(CONFIG_PCI) += pci.o vpdinfo.o
 obj-$(CONFIG_SMP) += smp.o
 obj-$(CONFIG_VIOPATH) += viopath.o
 obj-$(CONFIG_MODULES) += ksyms.o
+
+$(obj)/dt_mod.o:	$(obj)/dt.o
+	@$(OBJCOPY) --rename-section .rodata.str1.8=.dt_strings $(obj)/dt.o $(obj)/dt_mod.o
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 93d4233..0371329 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -30,6 +30,7 @@ #include <asm/lppaca.h>
 #include <asm/page.h>
 #include <asm/cputable.h>
 #include <asm/abs_addr.h>
+#include <asm/system.h>
 #include <asm/iseries/hv_types.h>
 #include <asm/iseries/hv_lp_config.h>
 #include <asm/iseries/hv_call_xm.h>
@@ -47,6 +48,9 @@ #else
 #define DBG(fmt...)
 #endif
 
+extern char __dt_strings_start[];
+extern char __dt_strings_end[];
+
 struct blob {
 	unsigned char data[PAGE_SIZE * 2];
 	unsigned long next;
@@ -55,26 +59,34 @@ struct blob {
 struct iseries_flat_dt {
 	struct boot_param_header header;
 	u64 reserve_map[2];
-	struct blob dt;
-	struct blob strings;
+	struct blob *dt;
 };
 
-static struct iseries_flat_dt iseries_dt;
+static struct iseries_flat_dt *iseries_dt;
 
-static void __init dt_init(struct iseries_flat_dt *dt)
+static struct iseries_flat_dt * __init dt_init(void)
 {
+	struct iseries_flat_dt *dt;
+	unsigned long str_len;
+
+	str_len = __dt_strings_end - __dt_strings_start;
+	dt = (struct iseries_flat_dt *)ALIGN(klimit, 8);
 	dt->header.off_mem_rsvmap =
 		offsetof(struct iseries_flat_dt, reserve_map);
-	dt->header.off_dt_struct = offsetof(struct iseries_flat_dt, dt);
-	dt->header.off_dt_strings = offsetof(struct iseries_flat_dt, strings);
-	dt->header.totalsize = sizeof(struct iseries_flat_dt);
-	dt->header.dt_strings_size = sizeof(struct blob);
+	dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
+	dt->header.off_dt_struct = dt->header.off_dt_strings
+		+ ALIGN(str_len, 8);
+	dt->dt = (struct blob *)((unsigned long)dt + dt->header.off_dt_struct);
+	klimit = ALIGN((unsigned long)(dt->dt) + sizeof(struct blob), 8);
+	dt->header.totalsize = klimit - (unsigned long)dt;
+	dt->header.dt_strings_size = str_len;
 
 	/* There is no notion of hardware cpu id on iSeries */
 	dt->header.boot_cpuid_phys = smp_processor_id();
 
-	dt->dt.next = (unsigned long)&dt->dt.data;
-	dt->strings.next = (unsigned long)&dt->strings.data;
+	dt->dt->next = (unsigned long)&dt->dt->data;
+	memcpy((char *)dt + dt->header.off_dt_strings, __dt_strings_start,
+			str_len);
 
 	dt->header.magic = OF_DT_HEADER;
 	dt->header.version = 0x10;
@@ -82,6 +94,8 @@ static void __init dt_init(struct iserie
 
 	dt->reserve_map[0] = 0;
 	dt->reserve_map[1] = 0;
+
+	return dt;
 }
 
 static void __init dt_check_blob(struct blob *b)
@@ -94,19 +108,19 @@ static void __init dt_check_blob(struct 
 
 static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
 {
-	*((u32*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u32);
+	*((u32*)dt->dt->next) = value;
+	dt->dt->next += sizeof(u32);
 
-	dt_check_blob(&dt->dt);
+	dt_check_blob(dt->dt);
 }
 
 #ifdef notyet
 static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
 {
-	*((u64*)dt->dt.next) = value;
-	dt->dt.next += sizeof(u64);
+	*((u64*)dt->dt->next) = value;
+	dt->dt->next += sizeof(u64);
 
-	dt_check_blob(&dt->dt);
+	dt_check_blob(dt->dt);
 }
 #endif
 
@@ -125,7 +139,7 @@ static unsigned long __init dt_push_byte
 static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
 {
 	dt_push_u32(dt, OF_DT_BEGIN_NODE);
-	dt_push_bytes(&dt->dt, name, strlen(name) + 1);
+	dt_push_bytes(dt->dt, name, strlen(name) + 1);
 }
 
 #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
@@ -140,14 +154,13 @@ static void __init dt_prop(struct iserie
 	/* Length of the data */
 	dt_push_u32(dt, len);
 
-	/* Put the property name in the string blob. */
-	offset = dt_push_bytes(&dt->strings, name, strlen(name) + 1);
+	offset = name - __dt_strings_start;
 
 	/* The offset of the properties name in the string blob. */
 	dt_push_u32(dt, (u32)offset);
 
 	/* The actual data. */
-	dt_push_bytes(&dt->dt, data, len);
+	dt_push_bytes(dt->dt, data, len);
 }
 
 static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
@@ -579,40 +592,45 @@ static void __init dt_pci_devices(struct
 	}
 }
 
+static void dt_finish(struct iseries_flat_dt *dt)
+{
+	dt_push_u32(dt, OF_DT_END);
+}
+
 void * __init build_flat_dt(unsigned long phys_mem_size)
 {
 	u64 tmp[2];
 
-	dt_init(&iseries_dt);
+	iseries_dt = dt_init();
 
-	dt_start_node(&iseries_dt, "");
+	dt_start_node(iseries_dt, "");
 
-	dt_prop_u32(&iseries_dt, "#address-cells", 2);
-	dt_prop_u32(&iseries_dt, "#size-cells", 2);
-	dt_model(&iseries_dt);
+	dt_prop_u32(iseries_dt, "#address-cells", 2);
+	dt_prop_u32(iseries_dt, "#size-cells", 2);
+	dt_model(iseries_dt);
 
 	/* /memory */
-	dt_start_node(&iseries_dt, "memory@0");
-	dt_prop_str(&iseries_dt, "name", "memory");
-	dt_prop_str(&iseries_dt, "device_type", "memory");
+	dt_start_node(iseries_dt, "memory@0");
+	dt_prop_str(iseries_dt, "name", "memory");
+	dt_prop_str(iseries_dt, "device_type", "memory");
 	tmp[0] = 0;
 	tmp[1] = phys_mem_size;
-	dt_prop_u64_list(&iseries_dt, "reg", tmp, 2);
-	dt_end_node(&iseries_dt);
+	dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
+	dt_end_node(iseries_dt);
 
 	/* /chosen */
-	dt_start_node(&iseries_dt, "chosen");
-	dt_prop_str(&iseries_dt, "bootargs", cmd_line);
-	dt_end_node(&iseries_dt);
+	dt_start_node(iseries_dt, "chosen");
+	dt_prop_str(iseries_dt, "bootargs", cmd_line);
+	dt_end_node(iseries_dt);
 
-	dt_cpus(&iseries_dt);
+	dt_cpus(iseries_dt);
 
-	dt_vdevices(&iseries_dt);
-	dt_pci_devices(&iseries_dt);
+	dt_vdevices(iseries_dt);
+	dt_pci_devices(iseries_dt);
 
-	dt_end_node(&iseries_dt);
+	dt_end_node(iseries_dt);
 
-	dt_push_u32(&iseries_dt, OF_DT_END);
+	dt_finish(iseries_dt);
 
-	return &iseries_dt;
+	return iseries_dt;
 }
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 14/14] powerpc: cleanup of iSeries flat device tree
  2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
                   ` (11 preceding siblings ...)
  2006-05-19  7:04 ` [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic Stephen Rothwell
@ 2006-05-19  7:06 ` Stephen Rothwell
  12 siblings, 0 replies; 14+ messages in thread
From: Stephen Rothwell @ 2006-05-19  7:06 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev

Consolidate the vio device node creation.  Make some parameters const.
Make a few more things __initdata. Get the device_type strings out of
the device tree blob.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---

 arch/powerpc/platforms/iseries/dt.c |  199 ++++++++++++++++++-----------------
 1 files changed, 101 insertions(+), 98 deletions(-)

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

89435c92f9a6d37d8d47bf40acde012726780f7f
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 2a51ec1..d3444aa 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -47,16 +47,34 @@ #else
 #define DBG(fmt...)
 #endif
 
+/*
+ * These are created by the linker script at the start and end
+ * of the section containing all the strings from this file.
+ */
 extern char __dt_strings_start[];
 extern char __dt_strings_end[];
 
 struct iseries_flat_dt {
 	struct boot_param_header header;
 	u64 reserve_map[2];
-	void *data;
 };
 
-static struct iseries_flat_dt *iseries_dt;
+static void * __initdata dt_data;
+
+/*
+ * Putting these strings here keeps them out of the section
+ * that we rename to .dt_strings using objcopy and capture
+ * for the strings blob of the flattened device tree.
+ */
+static char __initdata device_type_cpu[] = "cpu";
+static char __initdata device_type_memory[] = "memory";
+static char __initdata device_type_serial[] = "serial";
+static char __initdata device_type_network[] = "network";
+static char __initdata device_type_block[] = "block";
+static char __initdata device_type_byte[] = "byte";
+static char __initdata device_type_pci[] = "pci";
+static char __initdata device_type_vdevice[] = "vdevice";
+static char __initdata device_type_vscsi[] = "vscsi";
 
 static struct iseries_flat_dt * __init dt_init(void)
 {
@@ -70,7 +88,7 @@ static struct iseries_flat_dt * __init d
 	dt->header.off_dt_strings = ALIGN(sizeof(*dt), 8);
 	dt->header.off_dt_struct = dt->header.off_dt_strings
 		+ ALIGN(str_len, 8);
-	dt->data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
+	dt_data = (void *)((unsigned long)dt + dt->header.off_dt_struct);
 	dt->header.dt_strings_size = str_len;
 
 	/* There is no notion of hardware cpu id on iSeries */
@@ -91,26 +109,26 @@ static struct iseries_flat_dt * __init d
 
 static void __init dt_push_u32(struct iseries_flat_dt *dt, u32 value)
 {
-	*((u32 *)dt->data) = value;
-	dt->data += sizeof(u32);
+	*((u32 *)dt_data) = value;
+	dt_data += sizeof(u32);
 }
 
 #ifdef notyet
 static void __init dt_push_u64(struct iseries_flat_dt *dt, u64 value)
 {
-	*((u64 *)dt->data) = value;
-	dt->data += sizeof(u64);
+	*((u64 *)dt_data) = value;
+	dt_data += sizeof(u64);
 }
 #endif
 
-static void __init dt_push_bytes(struct iseries_flat_dt *dt, char *data,
+static void __init dt_push_bytes(struct iseries_flat_dt *dt, const char *data,
 		int len)
 {
-	memcpy(dt->data, data, len);
-	dt->data += ALIGN(len, 4);
+	memcpy(dt_data, data, len);
+	dt_data += ALIGN(len, 4);
 }
 
-static void __init dt_start_node(struct iseries_flat_dt *dt, char *name)
+static void __init dt_start_node(struct iseries_flat_dt *dt, const char *name)
 {
 	dt_push_u32(dt, OF_DT_BEGIN_NODE);
 	dt_push_bytes(dt, name, strlen(name) + 1);
@@ -118,8 +136,8 @@ static void __init dt_start_node(struct 
 
 #define dt_end_node(dt) dt_push_u32(dt, OF_DT_END_NODE)
 
-static void __init dt_prop(struct iseries_flat_dt *dt, char *name,
-		void *data, int len)
+static void __init dt_prop(struct iseries_flat_dt *dt, const char *name,
+		const void *data, int len)
 {
 	unsigned long offset;
 
@@ -137,36 +155,40 @@ static void __init dt_prop(struct iserie
 	dt_push_bytes(dt, data, len);
 }
 
-static void __init dt_prop_str(struct iseries_flat_dt *dt, char *name,
-		char *data)
+static void __init dt_prop_str(struct iseries_flat_dt *dt, const char *name,
+		const char *data)
 {
 	dt_prop(dt, name, data, strlen(data) + 1); /* + 1 for NULL */
 }
 
-static void __init dt_prop_u32(struct iseries_flat_dt *dt, char *name, u32 data)
+static void __init dt_prop_u32(struct iseries_flat_dt *dt, const char *name,
+		u32 data)
 {
 	dt_prop(dt, name, &data, sizeof(u32));
 }
 
-static void __init dt_prop_u64(struct iseries_flat_dt *dt, char *name, u64 data)
+#ifdef notyet
+static void __init dt_prop_u64(struct iseries_flat_dt *dt, const char *name,
+		u64 data)
 {
 	dt_prop(dt, name, &data, sizeof(u64));
 }
+#endif
 
-static void __init dt_prop_u64_list(struct iseries_flat_dt *dt, char *name,
-		u64 *data, int n)
+static void __init dt_prop_u64_list(struct iseries_flat_dt *dt,
+		const char *name, u64 *data, int n)
 {
 	dt_prop(dt, name, data, sizeof(u64) * n);
 }
 
-static void __init dt_prop_u32_list(struct iseries_flat_dt *dt, char *name,
-		u32 *data, int n)
+static void __init dt_prop_u32_list(struct iseries_flat_dt *dt,
+		const char *name, u32 *data, int n)
 {
 	dt_prop(dt, name, data, sizeof(u32) * n);
 }
 
 #ifdef notyet
-static void __init dt_prop_empty(struct iseries_flat_dt *dt, char *name)
+static void __init dt_prop_empty(struct iseries_flat_dt *dt, const char *name)
 {
 	dt_prop(dt, name, NULL, 0);
 }
@@ -199,7 +221,7 @@ static void __init dt_cpus(struct iserie
 		snprintf(p, 32 - (p - buf), "@%d", i);
 		dt_start_node(dt, buf);
 
-		dt_prop_str(dt, "device_type", "cpu");
+		dt_prop_str(dt, "device_type", device_type_cpu);
 
 		index = lppaca[i].dyn_hv_phys_proc_index;
 		d = &xIoHriProcessorVpd[index];
@@ -244,32 +266,41 @@ static void __init dt_model(struct iseri
 	dt_prop_str(dt, "compatible", "IBM,iSeries");
 }
 
+static void __init dt_do_vdevice(struct iseries_flat_dt *dt,
+		const char *name, u32 reg, int unit,
+		const char *type, const char *compat, int end)
+{
+	char buf[32];
+
+	snprintf(buf, 32, "%s@%08x", name, reg + ((unit >= 0) ? unit : 0));
+	dt_start_node(dt, buf);
+	dt_prop_str(dt, "device_type", type);
+	if (compat)
+		dt_prop_str(dt, "compatible", compat);
+	dt_prop_u32(dt, "reg", reg + ((unit >= 0) ? unit : 0));
+	if (unit >= 0)
+		dt_prop_u32(dt, "linux,unit_address", unit);
+	if (end)
+		dt_end_node(dt);
+}
+
 static void __init dt_vdevices(struct iseries_flat_dt *dt)
 {
 	u32 reg = 0;
 	HvLpIndexMap vlan_map;
 	int i;
-	char buf[32];
 
 	dt_start_node(dt, "vdevice");
-	dt_prop_str(dt, "device_type", "vdevice");
+	dt_prop_str(dt, "device_type", device_type_vdevice);
 	dt_prop_str(dt, "compatible", "IBM,iSeries-vdevice");
 	dt_prop_u32(dt, "#address-cells", 1);
 	dt_prop_u32(dt, "#size-cells", 0);
 
-	snprintf(buf, sizeof(buf), "vty@%08x", reg);
-	dt_start_node(dt, buf);
-	dt_prop_str(dt, "device_type", "serial");
-	dt_prop_u32(dt, "reg", reg);
-	dt_end_node(dt);
+	dt_do_vdevice(dt, "vty", reg, -1, device_type_serial, NULL, 1);
 	reg++;
 
-	snprintf(buf, sizeof(buf), "v-scsi@%08x", reg);
-	dt_start_node(dt, buf);
-	dt_prop_str(dt, "device_type", "vscsi");
-	dt_prop_str(dt, "compatible", "IBM,v-scsi");
-	dt_prop_u32(dt, "reg", reg);
-	dt_end_node(dt);
+	dt_do_vdevice(dt, "v-scsi", reg, -1, device_type_vscsi,
+			"IBM,v-scsi", 1);
 	reg++;
 
 	vlan_map = HvLpConfig_getVirtualLanIndexMap();
@@ -278,13 +309,8 @@ static void __init dt_vdevices(struct is
 
 		if ((vlan_map & (0x8000 >> i)) == 0)
 			continue;
-		snprintf(buf, 32, "l-lan@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "network");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-l-lan");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-
+		dt_do_vdevice(dt, "l-lan", reg, i, device_type_network,
+				"IBM,iSeries-l-lan", 0);
 		mac_addr[0] = 0x02;
 		mac_addr[1] = 0x01;
 		mac_addr[2] = 0xff;
@@ -300,47 +326,31 @@ static void __init dt_vdevices(struct is
 	}
 	reg += HVMAXARCHITECTEDVIRTUALLANS;
 
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++) {
-		snprintf(buf, 32, "viodasd@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "block");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-viodasd");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-		dt_end_node(dt);
-	}
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
+		dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
+				"IBM,iSeries-viodasd", 1);
 	reg += HVMAXARCHITECTEDVIRTUALDISKS;
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++) {
-		snprintf(buf, 32, "viocd@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "block");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-viocd");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-		dt_end_node(dt);
-	}
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
+		dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
+				"IBM,iSeries-viocd", 1);
 	reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++) {
-		snprintf(buf, 32, "viotape@%08x", reg + i);
-		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "byte");
-		dt_prop_str(dt, "compatible", "IBM,iSeries-viotape");
-		dt_prop_u32(dt, "reg", reg + i);
-		dt_prop_u32(dt, "linux,unit_address", i);
-		dt_end_node(dt);
-	}
+
+	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
+		dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
+				"IBM,iSeries-viotape", 1);
 
 	dt_end_node(dt);
 }
 
 struct pci_class_name {
 	u16 code;
-	char *name;
-	char *type;
+	const char *name;
+	const char *type;
 };
 
 static struct pci_class_name __initdata pci_class_name[] = {
-	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", "network" },
+	{ PCI_CLASS_NETWORK_ETHERNET, "ethernet", device_type_network },
 };
 
 static struct pci_class_name * __init dt_find_pci_class_name(u16 class_code)
@@ -384,9 +394,7 @@ static void __init scan_bridge_slot(stru
 					agent_id, 0);
 			if (err) {
 				if (err != 0x302)
-					printk(KERN_DEBUG
-						"connectBusUnit(%x, %x, %x) "
-						"== %x\n",
+					DBG("connectBusUnit(%x, %x, %x) %x\n",
 						bus, sub_bus, agent_id, err);
 				continue;
 			}
@@ -394,24 +402,21 @@ static void __init scan_bridge_slot(stru
 			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
 					PCI_VENDOR_ID, &vendor_id);
 			if (err) {
-				printk(KERN_DEBUG
-					"ReadVendor(%x, %x, %x) == %x\n",
+				DBG("ReadVendor(%x, %x, %x) %x\n",
 					bus, sub_bus, agent_id, err);
 				continue;
 			}
 			err = HvCallPci_configLoad16(bus, sub_bus, agent_id,
 					PCI_DEVICE_ID, &device_id);
 			if (err) {
-				printk(KERN_DEBUG
-					"ReadDevice(%x, %x, %x) == %x\n",
+				DBG("ReadDevice(%x, %x, %x) %x\n",
 					bus, sub_bus, agent_id, err);
 				continue;
 			}
 			err = HvCallPci_configLoad32(bus, sub_bus, agent_id,
 					PCI_CLASS_REVISION , &class_id);
 			if (err) {
-				printk(KERN_DEBUG
-					"ReadClass(%x, %x, %x) == %x\n",
+				DBG("ReadClass(%x, %x, %x) %x\n",
 					bus, sub_bus, agent_id, err);
 				continue;
 			}
@@ -470,19 +475,18 @@ static void __init scan_bridge(struct is
 		ret = HvCallXm_connectBusUnit(bus, sub_bus, agent_id, 0);
 		if (ret != 0) {
 			if (ret != 0xb)
-				printk(KERN_DEBUG "connectBusUnit(%x, %x, %x) "
-						"== %x\n",
+				DBG("connectBusUnit(%x, %x, %x) %x\n",
 						bus, sub_bus, agent_id, ret);
 			continue;
 		}
-		printk("found device at bus %d idsel %d func %d (AgentId %x)\n",
+		DBG("found device at bus %d idsel %d func %d (AgentId %x)\n",
 				bus, id_sel, function, agent_id);
 		ret = HvCallPci_getBusUnitInfo(bus, sub_bus, agent_id,
 				iseries_hv_addr(&bridge_info),
 				sizeof(struct HvCallPci_BridgeInfo));
 		if (ret != 0)
 			continue;
-		printk("bridge info: type %x subbus %x "
+		DBG("bridge info: type %x subbus %x "
 			"maxAgents %x maxsubbus %x logslot %x\n",
 			bridge_info.busUnitInfo.deviceType,
 			bridge_info.subBusNumber,
@@ -493,7 +497,7 @@ static void __init scan_bridge(struct is
 				HvCallPci_BridgeDevice)
 			scan_bridge_slot(dt, bus, &bridge_info);
 		else
-			printk("PCI: Invalid Bridge Configuration(0x%02X)",
+			DBG("PCI: Invalid Bridge Configuration(0x%02X)",
 				bridge_info.busUnitInfo.deviceType);
 	}
 }
@@ -515,13 +519,12 @@ static void __init scan_phb(struct iseri
 				sizeof(struct HvCallPci_DeviceInfo));
 		if (err) {
 			if (err != 0x302)
-				printk(KERN_DEBUG "getDeviceInfo(%x, %x, %x) "
-						"== %x\n",
+				DBG("getDeviceInfo(%x, %x, %x) %x\n",
 						bus, sub_bus, id_sel, err);
 			continue;
 		}
 		if (dev_info.deviceType != HvCallPci_NodeDevice) {
-			printk(KERN_DEBUG "PCI: Invalid System Configuration"
+			DBG("PCI: Invalid System Configuration"
 					"(0x%02X) for bus 0x%02x id 0x%02x.\n",
 					dev_info.deviceType, bus, id_sel);
 			continue;
@@ -547,14 +550,14 @@ static void __init dt_pci_devices(struct
 			 * something has gone wrong.
 			 */
 			if (err != 0x0301)
-				printk(KERN_ERR "Unexpected Return on Probe"
-						"(0x%02X): 0x%04X", bus, err);
+				DBG("Unexpected Return on Probe(0x%02X) "
+						"0x%04X\n", bus, err);
 			continue;
 		}
-		printk("bus %d appears to exist\n", bus);
+		DBG("bus %d appears to exist\n", bus);
 		snprintf(buf, 32, "pci@%d", phb_num);
 		dt_start_node(dt, buf);
-		dt_prop_str(dt, "device_type", "pci");
+		dt_prop_str(dt, "device_type", device_type_pci);
 		dt_prop_str(dt, "compatible", "IBM,iSeries-Logical-PHB");
 		dt_prop_u32(dt, "#address-cells", 3);
 		dt_prop_u32(dt, "#size-cells", 2);
@@ -569,12 +572,13 @@ static void __init dt_pci_devices(struct
 static void dt_finish(struct iseries_flat_dt *dt)
 {
 	dt_push_u32(dt, OF_DT_END);
-	dt->header.totalsize = (unsigned long)dt->data - (unsigned long)dt;
-	klimit = ALIGN((unsigned long)dt->data, 8);
+	dt->header.totalsize = (unsigned long)dt_data - (unsigned long)dt;
+	klimit = ALIGN((unsigned long)dt_data, 8);
 }
 
 void * __init build_flat_dt(unsigned long phys_mem_size)
 {
+	struct iseries_flat_dt *iseries_dt;
 	u64 tmp[2];
 
 	iseries_dt = dt_init();
@@ -587,8 +591,7 @@ void * __init build_flat_dt(unsigned lon
 
 	/* /memory */
 	dt_start_node(iseries_dt, "memory@0");
-	dt_prop_str(iseries_dt, "name", "memory");
-	dt_prop_str(iseries_dt, "device_type", "memory");
+	dt_prop_str(iseries_dt, "device_type", device_type_memory);
 	tmp[0] = 0;
 	tmp[1] = phys_mem_size;
 	dt_prop_u64_list(iseries_dt, "reg", tmp, 2);
-- 
1.3.1.ge923

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2006-05-19  7:11 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-19  6:42 [PATCH 01/14] powerpc: tidy up iseries/pci.c Stephen Rothwell
2006-05-19  6:43 ` [PATCH 02/14] powerpc: reintroduce HvCallPci_configLoad32 Stephen Rothwell
2006-05-19  6:46 ` [PATCH 03/14] powerpc: move iSeries PCI devices to the device tree Stephen Rothwell
2006-05-19  6:48 ` [PATCH 04/14] powerpc: remove iSeries_Global_Device_List Stephen Rothwell
2006-05-19  6:50 ` [PATCH 05/14] powerpc: remove Irq from pci_dn Stephen Rothwell
2006-05-19  6:51 ` [PATCH 06/14] powerpc: remove LogicalSlot " Stephen Rothwell
2006-05-19  6:53 ` [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute Stephen Rothwell
2006-05-19  6:54 ` [PATCH 08/14] powerpc: clean up iSeries PCI probe Stephen Rothwell
2006-05-19  6:55 ` [PATCH 09/14] powerpc: make iSeries flat device tree stuff static Stephen Rothwell
2006-05-19  6:58 ` [PATCH 10/14] powerpc: give iSeries device tree nodes better names Stephen Rothwell
2006-05-19  7:00 ` [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c Stephen Rothwell
2006-05-19  7:04 ` [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2 Stephen Rothwell
2006-05-19  7:04 ` [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic Stephen Rothwell
2006-05-19  7:06 ` [PATCH 14/14] powerpc: cleanup of iSeries flat device tree Stephen Rothwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).