LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 04/14] powerpc: remove iSeries_Global_Device_List
From: Stephen Rothwell @ 2006-05-19  6:48 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* [PATCH 05/14] powerpc: remove Irq from pci_dn
From: Stephen Rothwell @ 2006-05-19  6:50 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* [PATCH 06/14] powerpc: remove LogicalSlot from pci_dn
From: Stephen Rothwell @ 2006-05-19  6:51 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* [PATCH 07/14] powerpc: iSeries PCI devices can now have a devpsec attribute
From: Stephen Rothwell @ 2006-05-19  6:53 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>


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

* [PATCH 08/14] powerpc: clean up iSeries PCI probe
From: Stephen Rothwell @ 2006-05-19  6:54 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>


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

* [PATCH 09/14] powerpc: make iSeries flat device tree stuff static
From: Stephen Rothwell @ 2006-05-19  6:55 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>


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

* [PATCH 10/14] powerpc: give iSeries device tree nodes better names
From: Stephen Rothwell @ 2006-05-19  6:58 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* [PATCH 11/14] powerpc: split device tree stuff out of iseries/setup.c
From: Stephen Rothwell @ 2006-05-19  7:00 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>


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

* [PATCH 13/14] powerpc: make iSeries flattened device tree dynamic - part 2
From: Stephen Rothwell @ 2006-05-19  7:04 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* [PATCH 12/14] powerpc: make iSeries flattened device tree dynamic
From: Stephen Rothwell @ 2006-05-19  7:04 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* [PATCH 14/14] powerpc: cleanup of iSeries flat device tree
From: Stephen Rothwell @ 2006-05-19  7:06 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev
In-Reply-To: <20060519164249.2dc43bc4.sfr@canb.auug.org.au>

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

* Re: [Cbe-oss-dev] Cell and new CPU feature bits
From: Segher Boessenkool @ 2006-05-19  7:49 UTC (permalink / raw)
  To: Andrew Pinski
  Cc: Olof Johansson, linuxppc-dev list, cbe-oss-dev, Arnd Bergmann
In-Reply-To: <11D4E003-85A4-48A0-9654-BEAE5600B89C@physics.uc.edu>

>> I'm assuming you mean the instructions described under "AltiVec  
>> Memory
>> Bandwidth Management" in secion 5.2 of the Altivec PEM -- dst, dstt,
>> dstst, dss and dssall?
>
> They are nops on the Cell though.

And that is a compliant implementation.  I don't see a need
or real use for a feature bit here, esp. if we do get one for
the extended dcbt insns (which often are used as a replacement
for the data streaming insns).

> They are also microcoded on the 970.

No, they are cracked, instead.  Much lower hit.  They are completion
serialized though, so the only insn in an issue group, etc.


Segher

^ permalink raw reply

* Re: MPC8xx: resolution of gettimeofday() ?
From: Steven Scholz @ 2006-05-19  8:08 UTC (permalink / raw)
  To: linuxppc-embedded
In-Reply-To: <20060518164812.GA21075@gate.ebshome.net>

Eugene,

>> what is the resolution of gettimeofday() for an MPC8xx?
>>
>> IIUC then the "decrementer" is used to generate the timer interrupts every 10ms.
>>
>> This decrementer runs at cpuclk/16. Thus with 80MHz CPU clock has a
>> resolution of 16/80MHz = 200ns and overflows every 50000 ticks.
>>
>> But is this decrementer used to update xtime?
>> Will gettimeofday() have a resolution of 200ns?
>>
>> How about linux 2.4 where xtime is a "struct timeval" rather then "struct
>> timespec"?
>>
> 
> Usually on PPC we use timebase to interpolate time between Decrementer 
> interrupts. In this case gettimeofday resolution is determined by 
> timebase resolution which is quite high (megahertz range).

Sorry. I don't understand. What do you mean with "timebase"? Is there a
second timer/counter?

-- 
Steven

^ permalink raw reply

* Re: Cell and new CPU feature bits
From: Gabriel Paubert @ 2006-05-19  8:16 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev list, Paul Mackerras, cbe-oss-dev, Arnd Bergmann
In-Reply-To: <1148011621.13249.7.camel@localhost.localdomain>

On Fri, May 19, 2006 at 02:07:01PM +1000, Benjamin Herrenschmidt wrote:
> The Cell has a couple of "features" that should be exposed to userland
> in a way or another. That raises some questions however about how those
> should be done. Among others that come to mind:
> 
>  - The timebase errata (should we use a separate aux vector for "bugs"
> than for "features" ?

Is this bug really going to be exposed in the wild or is it
an early silicon bug that will only bite early-testers?

>  - Additional Altivec instructions (load/store right/left). A new
> feature bit for these ?

Yes. So IBM was not happy with Altivec instructions to generate
vsel control words and got their inspiration from MIPS?

>  - Lack of data stream instructions. Until now, it was assumed that
> those were tied to the presence
>    of an Altivec (and they are documented in the Altivec manual). Maybe
> we should split that to a
>    new bit. I don't know if existing applications use them though, if
> they do, there will be a 
>    problem to get them updated as the new bit isn't present on older
> kernels...

Is it really important? These instructions become nop on Cell, so their
impact on performance should be minimal while they may be useful in
code designed to run on any processor having Altivec.

>  - Extended implementation of dcbt. (Another bit ? Or sould we just have
> a "CELL" bit ? In which
>    case should it cover the altivec additions too or are those likely to
> exist in future non-Cell 
>    processors ?)

I believe that a Cell bit would be useful. After all you need a bit
that tell you that you have the SPUs and related infrastructure?

>  - Not strictly Cell specific but we currently don't expose the support
> for optional instructions
>    fres and frsqte (which are supported by Cell)

Should be exposed IMHO. But these instructions have been present
in a lot of PPC processors AFAIR, they are in my original 603 and
604 manuals from 1994 (fsel is also marked as optional and is not
implemented on the 601, but I'm not sure it's really supported
anymore). I don't know about Power processors. 

> Part of the problem is that we only have 32 userland feature bits and
> for some reason decided to put the microarchitecture in there, thus we
> are running out fast...

It will have to be extended and perhaps become a variable length
structure, better sooner than later.

	Regards,
	Gabriel

^ permalink raw reply

* Re: [Cbe-oss-dev] Cell and new CPU feature bits
From: Arnd Bergmann @ 2006-05-19 10:11 UTC (permalink / raw)
  To: cbe-oss-dev; +Cc: linuxppc-dev list
In-Reply-To: <1148011621.13249.7.camel@localhost.localdomain>

On Friday 19 May 2006 06:07, Benjamin Herrenschmidt wrote:
>  - Extended implementation of dcbt. (Another bit ? Or sould we just have
> a "CELL" bit ? In which case should it cover the altivec additions too
> or are those likely to exist in future non-Cell processors ?)

Isn't that already covered by PPC_FEATURE_CELL? Git log shows

| commit a7ddc5e85351931b67a48afa22788d77763837d8
| Author: Paul Mackerras <paulus@samba.org>
| Date:   Thu Nov 10 14:29:18 2005 +1100
|
|    powerpc: Add user CPU features for POWER4, POWER5, POWER5+ and Cell.
|
|    This is at the request of the glibc folks, who want to use these bits
|    to select libraries optimized for the microarchitecture and new
|    instructions in these processors.
|
|    Signed-off-by: Paul Mackerras <paulus@samba.org>

	Arnd <><

^ permalink raw reply

* i2sbus transfer foo
From: Johannes Berg @ 2006-05-19 11:36 UTC (permalink / raw)
  To: linuxppc-dev list

[-- Attachment #1: Type: text/plain, Size: 4292 bytes --]

Sorry for the vague subject :) I don't really know what to say...

Let me introduce some things first. First of all, the i2sbus controllers
Apple has in their mac-io chip are capable of doing (among others we
don't care about) 16-bit transfers in 32x and 64x i2s modes, and 24-bit
transfers in 64x i2s mode. For the latter, the chip requires that the
inputs are actually 32-bit aligned, which means that it's a bit weird
that it doesn't actually transfer all the 32 bits. But that's another
issue, maybe there's a way to make it transfer 32 bits that I don't
know. Or maybe it even does and we just don't have a codec capable of
using or creating data in those remaining 8 bits.

Anyway, let's dive right in, here's a sample capture where I was
capturing an 880Hz sine wave generated with gstreamer on another machine
via a direct cable:

00007910  f8 36 48 00 f7 a1 cc 00  f7 a1 cc 00 f7 2e ea 00  |.6H.............|
00007920  f7 2e ea 00 f6 df 58 00  f6 df 58 00 f6 b4 ee 00  |......X...X.....|
00007930  f6 b4 ee 00 f6 af 78 00  f6 af 78 00 f6 cf 59 00  |......x...x...Y.|

The hexdump above is directly from the DMA memory area, not gone through
alsa, I made a debugfs file that gives me access to the buffer area
straight away.

Let me start arecord again:
$ arecord -r 44100 -f S32_LE -c2 > /tmp/test.wav

Dumping the dma area again yields:
00008680  e4 00 ff bd e4 00 fe 93  22 00 fe 93 22 00 fd 6f  |........"..."..o|
00008690  2b 00 fd 6f 2b 00 fc 55  62 00 fc 55 62 00 fb 49  |+..o+..Ub..Ub..I|
000086a0  76 00 fb 49 76 00 fa 52  49 00 fa 52 49 00 f9 71  |v..Iv..RI..RI..q|
000086b0  1f 00 f9 71 1f 00 f8 aa  2c 00 f8 aa 2c 00 f7 ff  |...q....,...,...|
and a 3rd time:
0000ff60  00 07 3a 12 00 06 6f 77  00 06 6f 77 00 05 89 d9  |..:...ow..ow....|
0000ff70  00 05 89 d9 00 04 8e 73  00 04 8e 73 00 03 80 4a  |.......s...s...J|
0000ff80  00 03 80 4a 00 02 64 b0  00 02 64 b0 00 01 3e c0  |...J..d...d...>.|
0000ff90  00 01 3e c0 00 00 16 65  00 00 16 65 00 fe ea b6  |..>....e...e....|
4th time it's like 3rd, 5th like first, but 6th time:
0000bc60  e8 39 00 00 13 60 00 00  13 60 00 01 3d 96 00 01  |.9...`...`..=...|
0000bc70  3d 96 00 02 63 55 00 02  63 55 00 03 7f f5 00 03  |=...cU..cU......|
0000bc80  7f f5 00 04 8b 73 00 04  8b 73 00 05 87 84 00 05  |.....s...s......|
0000bc90  87 84 00 06 6d cc 00 06  6d cc 00 07 37 ae 00 07  |....m...m...7...|

See the problem?

When I actually manage to have it aligned like in #3 above,
SNDRV_PCM_FORMAT_S24_BE would be correct. And in that case, I once even
got a nice wav file that audacity can downsample to 16 bit and play
properly. But in all other cases I get mangled sound for obvious
reasons.

The correct data layout seems to be the first though, because when I
transfer that *to* the chip for playback (by making i2sbus announce
32bit big-endian format to alsa) I get proper sound with the correct
volume, hence I just changed i2sbus to always announce 16 and 32-bit BE
formats which also no longer mangles sound with gstreamer (except for
clicking every once a while on some streams[1]).

Oh, and note that those 4 cases aren't all possible cases. If you think
about it you'll notice that there are 8 cases because we have two
channels. I think I even mixed them in the dumps above, not sure.

Some looking at snd-powermac code later I now changed the i2sbus code to
do a dbdma-programmed engine stop in hope that would synchronize (as a
comment in snd-powermac implies) but that doesn't seem to be correct
either. I now more often get the first case though not all the time.

I'm out of ideas. I don't have a clue how to get this thing synchronized
properly. If anyone has a solution let me know, otherwise I'll probably
just disable 24-bit recording for good, then at least the chances of
getting sound that makes sense (even if left and right might be
switched) are 1/2 as opposed to 1/4 assuming even distribution... Also,
the question is why this does not happen on playback, or at least so
much less frequently that I haven't seen it yet...

johannes

[1] only happens with gstreamer on some streams, and then only if I use
alsasink without giving it the latency-time option, even if I give it
the default it doesn't click. very strange.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: snd-aoa status update / automatic driver loading
From: Johannes Berg @ 2006-05-19 10:22 UTC (permalink / raw)
  To: Tony Vroon; +Cc: linuxppc-dev list, Benjamin Berg, debian-powerpc
In-Reply-To: <446B721D.8020203@gentoo.org>

[-- Attachment #1: Type: text/plain, Size: 4514 bytes --]

On Wed, 2006-05-17 at 19:57 +0100, Tony Vroon wrote:

> When writing documentation, you might want to add that the ALSA-plugin
> in XMMS & Audacious requires a period time of 100ms instead of the
> default of 50ms, as otherwise the sou*click*nd is n*click*ot ver*click*y
> good.
> (A look at the current code of that plugin, to see how the volume
> control code can be fixed would be highly appreciated)

How's that related to snd-aoa? You can currently buffer up to 131072
bytes which at 96KHz and 32 bits is ~171ms. At the regular 44100Hz/16bit
it is ~743ms. But you can easily increase that in i2sbus-pcm.c line
126ff:
        /* these are somewhat arbitrary */
        hw->buffer_bytes_max = 131072;
        hw->period_bytes_min = 256;
        hw->period_bytes_max = 16384;
The thing is just that this memory area is essentially mlock()ed so if I
did indeed allow 16k per period and 32 periods the stream would mlock
512K. What would others say is appropriate?

Ah then again I can see how this might be related to snd-aoa -- we only
update the pcm position on each period so maybe we should increase the
minimum number of periods. Can you try that? Go into i2sbus-pcm.c line
130 and change
        hw->periods_min = 3;
to maybe 6. Or just try binary search for  smallest value that makes it
work (if it ever does, but I think it should, if this is indeed the
issue). Indeed, at 50ms buffer you have just 8820 bytes which can even
be divided by 3 so that probably means that xmms used 3 periods. Maybe
that's a bit tight. Do you see the same issue with snd-powermac? (it
uses the same period setup)

> Not seen this, although I must say it does not resume from sleep as
> gracefully as I have seen you describe it.

What happens? I just fixed tas resume from sleep (by completely
re-initialising the codec) and something similar should be done for the
onyx probably (or do I do that already?) for suspend to disk, but other
than that... Oh I just realised that it'll lose some sound due to
restarting the dma command ring at the beginning. Hmm. I suppose I can
change that easily, will have to do some testing.

Benjamin (Berg), can we do that even with the lost interrupt issue?

Maybe both of these issues can be fixed by using the frame count
register instead to count how many samples were played? Below is a small
patch to print out a lot of frame count numbers, Benjamin, I'd
appreciate if you could look how this interacted with the lost
interrupts.

Note that for this to work we'd of course have to sample the frame count
register right before starting the DMA engine, it increases even while
we're not playing because we don't stop the clocks. We probably should
do that too for powersaving. Humm. Lots to do :) Oh and this probably
means that yes, it works fine even when we do lose interrupts. 

Alternatively we could use the register just to detect if we lost
interrupts, i.e. calculate how many frames we have per period and then
see if the frame count increased approximately by that much (I've seen
+- a few frames probably due to timing, with higher samplerates we'll
probably see a bit more error) and if it increased by much more we could
estimate how many interrupts we lost. What do you think?

johannes

--- snd-aoa.orig/soundbus/i2sbus/i2sbus-pcm.c	2006-05-19 12:10:16.919474526 +0200
+++ snd-aoa/soundbus/i2sbus/i2sbus-pcm.c	2006-05-19 12:11:22.119474526 +0200
@@ -488,12 +488,17 @@ static snd_pcm_uframes_t i2sbus_pcm_poin
 static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
 {
 	struct pcm_info *pi;
+	u32 fc;
 
 	get_pcm_info(i2sdev, in, &pi, NULL);
 	if (!pi->substream) {
 		printk(KERN_INFO "i2sbus: got %s irq while not active!\n", in?"rx":"tx");
 		return;
 	}
+	fc = in_le32(&i2sdev->intfregs->frame_count);
+	printk(KERN_DEBUG "i2sbus: frame count is %d\n", fc);
+	printk(KERN_DEBUG "i2sbus: delta fc = %d\n", fc - i2sdev->fc);
+	i2sdev->fc = fc;
 	pi->current_period = (pi->current_period+1) % (pi->periods);
 	snd_pcm_period_elapsed(pi->substream);
 }
--- snd-aoa.orig/soundbus/i2sbus/i2sbus.h	2006-05-19 12:10:16.919474526 +0200
+++ snd-aoa/soundbus/i2sbus/i2sbus.h	2006-05-19 12:11:22.119474526 +0200
@@ -50,6 +50,7 @@ struct i2sbus_dev {
 	struct macio_dev *macio;
 	struct i2sbus_control *control;
 	volatile struct i2s_interface_regs __iomem *intfregs;
+	u32 fc;
 
 	int resource_allocated; /* bitmask of resources */
 	struct resource resources[3];


[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: PowerMac7,3 sound (was: PowerBook5,4 -- no sound?)
From: Johannes Berg @ 2006-05-19 12:47 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev
In-Reply-To: <jek68jqz1l.fsf@sykes.suse.de>

[-- Attachment #1: Type: text/plain, Size: 222 bytes --]

On Thu, 2006-05-18 at 14:48 +0200, Andreas Schwab wrote:

> Yes, that's while I had that loaded.  Of course, I unloaded it before I
> tried snd-aoa.

Ok, but is that the correct stuff, i.e. does it work?

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: snd-aoa status update / automatic driver loading
From: Johannes Berg @ 2006-05-19 12:50 UTC (permalink / raw)
  To: Wolfgang Pfeiffer; +Cc: linuxppc-dev list, debian-powerpc
In-Reply-To: <20060518181748.GA2836@localhost>

[-- Attachment #1: Type: text/plain, Size: 386 bytes --]

On Thu, 2006-05-18 at 20:17 +0200, Wolfgang Pfeiffer wrote:

> BTW: Is there a way to let 'alsaconf' detect the soundcard on this
> PB5,8 ?
> So far that's impossible, as it seems. But this could also be
> related to mistakes I made in my modules files, or wherever.

No idea, but I don't see why you'd want alsaconf to figure it out if the
kernel can by itself...

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: snd-aoa status update / automatic driver loading
From: Paul Collins @ 2006-05-19 13:20 UTC (permalink / raw)
  To: Johannes Berg; +Cc: list, Eddy Petrişor, debian-powerpc
In-Reply-To: <1147947784.15507.46.camel@johannes>

Johannes Berg <johannes@sipsolutions.net> writes:

> On Thu, 2006-05-18 at 10:25 +0300, Eddy Petri=C5=9For wrote:
>
>> Any chance for 5,2 ? What is needed for it? Codec only?
>
> I don't know. If you try loading the modules, the kernel will tell you
> something about an unhandled layout id. Alternatively, you can find the
> layout-id file in your /proc/device-tree/ and tell me the number in it.
> The rest I can figure out.

I have a PowerBook5,4 here and I'd be happy to test support for it.
The hardware is identified by snd-powermac as "PowerMac Snapper" and
the layout ID appears to be "3".

[briny(device-tree)] od -c pci@f2000000/mac-io@17/i2s@10000/i2s-a@10000/sou=
nd/layout-id
0000000  \0  \0  \0   3
0000004

--=20
Dag vijandelijk luchtschip de huismeester is dood

^ permalink raw reply

* Re: PowerMac7,3 sound (was: PowerBook5,4 -- no sound?)
From: Andreas Schwab @ 2006-05-19 13:30 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linuxppc-dev
In-Reply-To: <1148042866.3864.3.camel@johannes.berg>

Johannes Berg <johannes@sipsolutions.net> writes:

> On Thu, 2006-05-18 at 14:48 +0200, Andreas Schwab wrote:
>
>> Yes, that's while I had that loaded.  Of course, I unloaded it before I
>> tried snd-aoa.
>
> Ok, but is that the correct stuff, i.e. does it work?

Sorry, I can't quite figure out what "it" refers to in your question.

Andreas.

-- 
Andreas Schwab, SuSE Labs, schwab@suse.de
SuSE Linux Products GmbH, Maxfeldstraße 5, 90409 Nürnberg, Germany
PGP key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."

^ permalink raw reply

* Re: snd-aoa status update / automatic driver loading
From: Johannes Berg @ 2006-05-19 13:46 UTC (permalink / raw)
  To: Paul Collins; +Cc: linuxppc-dev list, debian-powerpc, Eddy Petrişor
In-Reply-To: <87wtcirw0y.fsf@briny.internal.ondioline.org>

[-- Attachment #1: Type: text/plain, Size: 415 bytes --]

On Fri, 2006-05-19 at 23:20 +1000, Paul Collins wrote:

> I have a PowerBook5,4 here and I'd be happy to test support for it.
> The hardware is identified by snd-powermac as "PowerMac Snapper" and
> the layout ID appears to be "3".

Try downloading snd-aoa and in snd-aoa-fabric-layout.c change the two
occurrences of '70' to '3'. If it works, let me know and I'll add the
proper entry for it.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* Re: PowerMac7,3 sound (was: PowerBook5,4 -- no sound?)
From: Johannes Berg @ 2006-05-19 13:48 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: linuxppc-dev
In-Reply-To: <jey7wynnux.fsf@sykes.suse.de>

[-- Attachment #1: Type: text/plain, Size: 668 bytes --]

On Fri, 2006-05-19 at 15:30 +0200, Andreas Schwab wrote:

> >> Yes, that's while I had that loaded.  Of course, I unloaded it before I
> >> tried snd-aoa.
> >
> > Ok, but is that the correct stuff, i.e. does it work?
> 
> Sorry, I can't quite figure out what "it" refers to in your question.

Sorry. I was trying to ask if you get sound with snd-powermac, i.e. if
the items

>>         80008000-800083ff : 0.00010000:i2s
>>           80008000-800083ff : Sound DMA
>>         80010000-80010fff : 0.00010000:i2s
>>           80010000-80010fff : Sound Control

are correct. I'll have to investigate a bit more what happens on your
machine.

johannes

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 793 bytes --]

^ permalink raw reply

* libspe update
From: D. Herrendoerfer @ 2006-05-19 13:56 UTC (permalink / raw)
  To: linuxppc64-dev

[-- Attachment #1: Type: text/plain, Size: 307 bytes --]

***********************
Warning: Your file, libspe-1.1.0-20060519.tar.gz, contains more than 32 files after decompression and cannot be scanned.
***********************


This is the current version of libspe matching the current spufs 
implementation
posted by Arnd Bergmann this week.

D. Herrendoerfer



[-- Attachment #2: libspe-1.1.0-20060519.tar.gz --]
[-- Type: application/x-gzip, Size: 53352 bytes --]

^ permalink raw reply

* Re: [PATCH 5/6] Have ia64 use add_active_range() and free_area_init_nodes
From: Mel Gorman @ 2006-05-19 14:03 UTC (permalink / raw)
  To: Andrew Morton
  Cc: davej, tony.luck, linuxppc-dev, ak, bob.picco, linux-kernel,
	linux-mm
In-Reply-To: <20060514203158.216a966e.akpm@osdl.org>

On Sun, 14 May 2006, Andrew Morton wrote:

> Mel Gorman <mel@csn.ul.ie> wrote:
>>
>> Size zones and holes in an architecture independent manner for ia64.
>>
>
> This one makes my ia64 die very early in boot.   The trace is pretty useless.
>
> config at http://www.zip.com.au/~akpm/linux/patches/stuff/config-ia64
>

An indirect fix for this has been set out with a patchset with the subject 
"[PATCH 0/2] Fixes for node alignment and flatmem assumptions" . For 
arch-independent-zone-sizing, the issue was that FLATMEM assumes that 
NODE_DATA(0)->node_start_pfn == 0. This is not the case with 
arch-independent-zone-sizing and IA64. With arch-independent-zone-sizing, 
a nodes node_start_pfn will be at the first valid PFN.

> <log snipped>
>
> Note the misaligned pfns.
>

You will still get the message about misaligned PFNs on IA64. This is 
because the lowest zone starts at the lowest available PFN which may not 
be 0 or any other aligned number. It shouldn't make a different - or at 
least I couldn't cause any problems.

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox