LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 09/11] [POWERPC] iSeries: move detection of virtual tapes
From: Stephen Rothwell @ 2007-09-23 16:52 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev, Christoph Hellwig
In-Reply-To: <20070921143841.37ad2a2f.sfr@canb.auug.org.au>

Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties).  This way viotape.c gets
all the information about the devices from the device tree.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/platforms/iseries/dt.c  |    7 --
 arch/powerpc/platforms/iseries/vio.c |  149 ++++++++++++++++++++++++++++++----
 drivers/char/viotape.c               |  124 ++++------------------------
 include/asm-powerpc/iseries/vio.h    |   41 +++++++++
 4 files changed, 192 insertions(+), 129 deletions(-)

This version creates the device tree entries unconditionally.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 84fcee1..2e4ad6b 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -73,7 +73,6 @@ 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";
@@ -380,12 +379,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
 	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
 		dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
 				"IBM,iSeries-viodasd", 1);
-	reg += HVMAXARCHITECTEDVIRTUALDISKS;
-	reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
-		dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
-				"IBM,iSeries-viotape", 1);
 
 	dt_end_node(dt);
 }
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 08f6884..b4f7433 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -45,6 +45,18 @@
 #define FIRST_VIOTAPE	(FIRST_VIOCD + NUM_VIOCDS)
 #define NUM_VIOTAPES	HVMAXARCHITECTEDVIRTUALTAPES
 
+struct vio_waitevent {
+	struct completion	com;
+	int			rc;
+	u16			sub_result;
+};
+
+struct vio_resource {
+	char	rsrcname[10];
+	char	type[4];
+	char	model[3];
+};
+
 static struct property * __init new_property(const char *name, int length,
 		const void *value)
 {
@@ -123,22 +135,10 @@ static int __init add_raw_property(struct device_node *np, const char *name,
 	return 1;
 }
 
-struct viocd_waitevent {
-	struct completion	com;
-	int			rc;
-	u16			sub_result;
-};
-
-struct cdrom_info {
-	char	rsrcname[10];
-	char	type[4];
-	char	model[3];
-};
-
 static void __init handle_cd_event(struct HvLpEvent *event)
 {
 	struct viocdlpevent *bevent;
-	struct viocd_waitevent *pwe;
+	struct vio_waitevent *pwe;
 
 	if (!event)
 		/* Notification that a partition went away! */
@@ -158,7 +158,7 @@ static void __init handle_cd_event(struct HvLpEvent *event)
 
 	switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
 	case viocdgetinfo:
-		pwe = (struct viocd_waitevent *)event->xCorrelationToken;
+		pwe = (struct vio_waitevent *)event->xCorrelationToken;
 		pwe->rc = event->xRc;
 		pwe->sub_result = bevent->sub_result;
 		complete(&pwe->com);
@@ -179,8 +179,8 @@ static void __init get_viocd_info(struct device_node *vio_root)
 {
 	HvLpEvent_Rc hvrc;
 	u32 unit;
-	struct viocd_waitevent we;
-	struct cdrom_info *unitinfo;
+	struct vio_waitevent we;
+	struct vio_resource *unitinfo;
 	dma_addr_t unitinfo_dmaaddr;
 	int ret;
 
@@ -286,6 +286,122 @@ static void __init get_viocd_info(struct device_node *vio_root)
 	viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
 }
 
+/* Handle interrupt events for tape */
+static void __init handle_tape_event(struct HvLpEvent *event)
+{
+	struct vio_waitevent *we;
+	struct viotapelpevent *tevent = (struct viotapelpevent *)event;
+
+	if (event == NULL)
+		/* Notification that a partition went away! */
+		return;
+
+	we = (struct vio_waitevent *)event->xCorrelationToken;
+	switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+	case viotapegetinfo:
+		we->rc = tevent->sub_type_result;
+		complete(&we->com);
+		break;
+	default:
+		printk(KERN_WARNING "handle_tape_event: weird ack\n");
+	}
+}
+
+static void __init get_viotape_info(struct device_node *vio_root)
+{
+	HvLpEvent_Rc hvrc;
+	u32 unit;
+	struct vio_resource *unitinfo;
+	dma_addr_t unitinfo_dmaaddr;
+	size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
+	struct vio_waitevent we;
+	int ret;
+
+	ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
+	if (ret) {
+		printk(KERN_WARNING "get_viotape_info: "
+			"error on viopath_open to hostlp %d\n", ret);
+		return;
+	}
+
+	vio_setHandler(viomajorsubtype_tape, handle_tape_event);
+
+	unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
+	if (!unitinfo)
+		goto clear_handler;
+
+	memset(unitinfo, 0, len);
+
+	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+			HvLpEvent_Type_VirtualIo,
+			viomajorsubtype_tape | viotapegetinfo,
+			HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+			viopath_sourceinst(viopath_hostLp),
+			viopath_targetinst(viopath_hostLp),
+			(u64)(unsigned long)&we, VIOVERSION << 16,
+			unitinfo_dmaaddr, len, 0, 0);
+	if (hvrc != HvLpEvent_Rc_Good) {
+		printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
+				(int)hvrc);
+		goto hv_free;
+	}
+
+	wait_for_completion(&we.com);
+
+	for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
+			unitinfo[unit].rsrcname[0]; unit++) {
+		struct device_node *np;
+		char name[64];
+		u32 reg = FIRST_VIOTAPE + unit;
+
+		snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
+		np = new_node(name, vio_root);
+		if (!np)
+			goto hv_free;
+		if (!add_string_property(np, "name", "viotape") ||
+			!add_string_property(np, "device_type", "byte") ||
+			!add_string_property(np, "compatible",
+				"IBM,iSeries-viotape") ||
+			!add_raw_property(np, "reg", sizeof(reg), &reg) ||
+			!add_raw_property(np, "linux,unit_address",
+				sizeof(unit), &unit) ||
+			!add_raw_property(np, "linux,vio_rsrcname",
+				sizeof(unitinfo[unit].rsrcname),
+				unitinfo[unit].rsrcname) ||
+			!add_raw_property(np, "linux,vio_type",
+				sizeof(unitinfo[unit].type),
+				unitinfo[unit].type) ||
+			!add_raw_property(np, "linux,vio_model",
+				sizeof(unitinfo[unit].model),
+				unitinfo[unit].model))
+			goto node_free;
+		np->name = of_get_property(np, "name", NULL);
+		np->type = of_get_property(np, "device_type", NULL);
+		of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+		if (vio_root->pde) {
+			struct proc_dir_entry *ent;
+
+			ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
+					vio_root->pde);
+			if (ent)
+				proc_device_tree_add_node(np, ent);
+		}
+#endif
+		continue;
+
+ node_free:
+		free_node(np);
+		break;
+	}
+
+ hv_free:
+	iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+	vio_clearHandler(viomajorsubtype_tape);
+	viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
+}
+
 static int __init iseries_vio_init(void)
 {
 	struct device_node *vio_root;
@@ -307,6 +423,7 @@ static int __init iseries_vio_init(void)
 	}
 
 	get_viocd_info(vio_root);
+	get_viotape_info(vio_root);
 
 	return 0;
 
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 064c091..f1d60f0 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -92,47 +92,6 @@ struct viot_devinfo_struct {
 #define VIOTAPOP_SETPART       14
 #define VIOTAPOP_UNLOAD        15
 
-struct viotapelpevent {
-	struct HvLpEvent event;
-	u32 reserved;
-	u16 version;
-	u16 sub_type_result;
-	u16 tape;
-	u16 flags;
-	u32 token;
-	u64 len;
-	union {
-		struct {
-			u32 tape_op;
-			u32 count;
-		} op;
-		struct {
-			u32 type;
-			u32 resid;
-			u32 dsreg;
-			u32 gstat;
-			u32 erreg;
-			u32 file_no;
-			u32 block_no;
-		} get_status;
-		struct {
-			u32 block_no;
-		} get_pos;
-	} u;
-};
-
-enum viotapesubtype {
-	viotapeopen = 0x0001,
-	viotapeclose = 0x0002,
-	viotaperead = 0x0003,
-	viotapewrite = 0x0004,
-	viotapegetinfo = 0x0005,
-	viotapeop = 0x0006,
-	viotapegetpos = 0x0007,
-	viotapesetpos = 0x0008,
-	viotapegetstatus = 0x0009
-};
-
 enum viotaperc {
 	viotape_InvalidRange = 0x0601,
 	viotape_InvalidToken = 0x0602,
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
 #define VIOT_WRITING		2
 
 /* Our info on the tapes */
-struct tape_descr {
-	char rsrcname[10];
-	char type[4];
-	char model[3];
-};
-
-static struct tape_descr *viotape_unitinfo;
-static dma_addr_t viotape_unitinfo_token;
+static struct {
+	const char *rsrcname;
+	const char *type;
+	const char *model;
+} viotape_unitinfo[VIOTAPE_MAX_TAPE];
 
 static struct mtget viomtget[VIOTAPE_MAX_TAPE];
 
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
 	return -err->errno;
 }
 
-/* Get info on all tapes from OS/400 */
-static int get_viotape_info(void)
-{
-	HvLpEvent_Rc hvrc;
-	int i;
-	size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
-	struct op_struct *op = get_op_struct();
-
-	if (op == NULL)
-		return -ENOMEM;
-
-	viotape_unitinfo = iseries_hv_alloc(len, &viotape_unitinfo_token,
-		GFP_ATOMIC);
-	if (viotape_unitinfo == NULL) {
-		free_op_struct(op);
-		return -ENOMEM;
-	}
-
-	memset(viotape_unitinfo, 0, len);
-
-	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
-			HvLpEvent_Type_VirtualIo,
-			viomajorsubtype_tape | viotapegetinfo,
-			HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
-			viopath_sourceinst(viopath_hostLp),
-			viopath_targetinst(viopath_hostLp),
-			(u64) (unsigned long) op, VIOVERSION << 16,
-			viotape_unitinfo_token, len, 0, 0);
-	if (hvrc != HvLpEvent_Rc_Good) {
-		printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
-				(int)hvrc);
-		free_op_struct(op);
-		return -EIO;
-	}
-
-	wait_for_completion(&op->com);
-
-	free_op_struct(op);
-
-	for (i = 0;
-	     ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
-	     i++)
-		viotape_numdev++;
-	return 0;
-}
-
-
 /* Write */
 static ssize_t viotap_write(struct file *file, const char *buf,
 		size_t count, loff_t * ppos)
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
 	tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
 	op = (struct op_struct *)event->xCorrelationToken;
 	switch (tapeminor) {
-	case viotapegetinfo:
 	case viotapeopen:
 	case viotapeclose:
 		op->rc = tevent->sub_type_result;
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 {
 	int i = vdev->unit_address;
 	int j;
+	struct device_node *node = vdev->dev.archdata.of_node;
 
-	if (i >= viotape_numdev)
+	if (i > VIOTAPE_MAX_TAPE)
+		return -ENODEV;
+	if (!node)
 		return -ENODEV;
 
+	if (i >= viotape_numdev)
+		viotape_numdev = i + 1;
+
 	tape_device[i] = &vdev->dev;
+	viotape_unitinfo[i].rsrcname = of_get_property(node,
+					"linux,vio_rsrcname", NULL);
+	viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
+					NULL);
+	viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
+					NULL);
 
 	state[i].cur_part = 0;
 	for (j = 0; j < MAX_PARTITIONS; ++j)
@@ -1044,11 +964,6 @@ int __init viotap_init(void)
 		goto unreg_chrdev;
 	}
 
-	if ((ret = get_viotape_info()) < 0) {
-		printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
-		goto unreg_class;
-	}
-
 	ret = vio_register_driver(&viotape_driver);
 	if (ret)
 		goto unreg_class;
@@ -1102,9 +1017,6 @@ static void __exit viotap_exit(void)
 	vio_unregister_driver(&viotape_driver);
 	class_destroy(tape_class);
 	unregister_chrdev(VIOTAPE_MAJOR, "viotape");
-	if (viotape_unitinfo)
-		iseries_hv_free(sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
-				viotape_unitinfo, viotape_unitinfo_token);
 	viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
 	vio_clearHandler(viomajorsubtype_tape);
 	clear_op_struct_pool();
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index e5a405b..2555dfd 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -75,6 +75,47 @@ enum viocdsubtype {
 	viocdcheck = 0x0007
 };
 
+struct viotapelpevent {
+	struct HvLpEvent event;
+	u32 reserved;
+	u16 version;
+	u16 sub_type_result;
+	u16 tape;
+	u16 flags;
+	u32 token;
+	u64 len;
+	union {
+		struct {
+			u32 tape_op;
+			u32 count;
+		} op;
+		struct {
+			u32 type;
+			u32 resid;
+			u32 dsreg;
+			u32 gstat;
+			u32 erreg;
+			u32 file_no;
+			u32 block_no;
+		} get_status;
+		struct {
+			u32 block_no;
+		} get_pos;
+	} u;
+};
+
+enum viotapesubtype {
+	viotapeopen = 0x0001,
+	viotapeclose = 0x0002,
+	viotaperead = 0x0003,
+	viotapewrite = 0x0004,
+	viotapegetinfo = 0x0005,
+	viotapeop = 0x0006,
+	viotapegetpos = 0x0007,
+	viotapesetpos = 0x0008,
+	viotapegetstatus = 0x0009
+};
+
 /*
  * Each subtype can register a handler to process their events.
  * The handler must have this interface.
-- 
1.5.3.2

^ permalink raw reply related

* [PATCH 11/11] [POWERPC] iSeries: move viodasd probing
From: Stephen Rothwell @ 2007-09-23 16:54 UTC (permalink / raw)
  To: paulus; +Cc: ppc-dev, Christoph Hellwig
In-Reply-To: <20070921144051.fe554f57.sfr@canb.auug.org.au>

This way we only have entries in the device tree for disks that actually
exist.  A slight complication is that disks may be attached to LPARs
at runtime.

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
 arch/powerpc/platforms/iseries/dt.c  |    6 -
 arch/powerpc/platforms/iseries/vio.c |  301 +++++++++++++++++++++++----------
 drivers/block/viodasd.c              |   77 +++------
 include/asm-powerpc/iseries/vio.h    |   47 ++++++
 4 files changed, 282 insertions(+), 149 deletions(-)

This version creates the device tree entries unconditionally.
-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au

diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 2e4ad6b..4543c4b 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -72,7 +72,6 @@ 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_pci[] = "pci";
 static char __initdata device_type_vdevice[] = "vdevice";
 static char __initdata device_type_vscsi[] = "vscsi";
@@ -374,11 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
 
 		dt_end_node(dt);
 	}
-	reg += HVMAXARCHITECTEDVIRTUALLANS;
-
-	for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
-		dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
-				"IBM,iSeries-viodasd", 1);
 
 	dt_end_node(dt);
 }
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index b4f7433..d6435b0 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -25,8 +25,10 @@
 #include <linux/gfp.h>
 #include <linux/completion.h>
 #include <linux/proc_fs.h>
+#include <linux/module.h>
 
 #include <asm/firmware.h>
+#include <asm/vio.h>
 #include <asm/iseries/vio.h>
 #include <asm/iseries/iommu.h>
 #include <asm/iseries/hv_types.h>
@@ -57,7 +59,7 @@ struct vio_resource {
 	char	model[3];
 };
 
-static struct property * __init new_property(const char *name, int length,
+static struct property *new_property(const char *name, int length,
 		const void *value)
 {
 	struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
@@ -78,7 +80,7 @@ static void __init free_property(struct property *np)
 	kfree(np);
 }
 
-static struct device_node * __init new_node(const char *path,
+static struct device_node *new_node(const char *path,
 		struct device_node *parent)
 {
 	struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
@@ -97,7 +99,7 @@ static struct device_node * __init new_node(const char *path,
 	return np;
 }
 
-static void __init free_node(struct device_node *np)
+static void free_node(struct device_node *np)
 {
 	struct property *next;
 	struct property *prop;
@@ -113,7 +115,7 @@ static void __init free_node(struct device_node *np)
 	kfree(np);
 }
 
-static int __init add_string_property(struct device_node *np, const char *name,
+static int add_string_property(struct device_node *np, const char *name,
 		const char *value)
 {
 	struct property *nprop = new_property(name, strlen(value) + 1, value);
@@ -124,7 +126,7 @@ static int __init add_string_property(struct device_node *np, const char *name,
 	return 1;
 }
 
-static int __init add_raw_property(struct device_node *np, const char *name,
+static int add_raw_property(struct device_node *np, const char *name,
 		int length, const void *value)
 {
 	struct property *nprop = new_property(name, length, value);
@@ -135,6 +137,201 @@ static int __init add_raw_property(struct device_node *np, const char *name,
 	return 1;
 }
 
+static struct device_node *do_device_node(struct device_node *parent,
+		const char *name, u32 reg, u32 unit, const char *type,
+		const char *compat, struct vio_resource *res)
+{
+	struct device_node *np;
+	char path[32];
+
+	snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
+	np = new_node(path, parent);
+	if (!np)
+		return NULL;
+	if (!add_string_property(np, "name", name) ||
+		!add_string_property(np, "device_type", type) ||
+		!add_string_property(np, "compatible", compat) ||
+		!add_raw_property(np, "reg", sizeof(reg), &reg) ||
+		!add_raw_property(np, "linux,unit_address",
+			sizeof(unit), &unit)) {
+		goto node_free;
+	}
+	if (res) {
+		if (!add_raw_property(np, "linux,vio_rsrcname",
+				sizeof(res->rsrcname), res->rsrcname) ||
+			!add_raw_property(np, "linux,vio_type",
+				sizeof(res->type), res->type) ||
+			!add_raw_property(np, "linux,vio_model",
+				sizeof(res->model), res->model))
+			goto node_free;
+	}
+	np->name = of_get_property(np, "name", NULL);
+	np->type = of_get_property(np, "device_type", NULL);
+	of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+	if (parent->pde) {
+		struct proc_dir_entry *ent;
+
+		ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
+		if (ent)
+			proc_device_tree_add_node(np, ent);
+	}
+#endif
+	return np;
+
+ node_free:
+	free_node(np);
+	return NULL;
+}
+
+/*
+ * This is here so that we can dynamically add viodasd
+ * devices without exposing all the above infrastructure.
+ */
+struct vio_dev *vio_create_viodasd(u32 unit)
+{
+	struct device_node *vio_root;
+	struct device_node *np;
+	struct vio_dev *vdev = NULL;
+
+	vio_root = of_find_node_by_path("/vdevice");
+	if (!vio_root)
+		return NULL;
+	np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+			"block", "IBM,iSeries-viodasd", NULL);
+	of_node_put(vio_root);
+	if (np) {
+		vdev = vio_register_device_node(np);
+		if (!vdev)
+			free_node(np);
+	}
+	return vdev;
+}
+EXPORT_SYMBOL_GPL(vio_create_viodasd);
+
+static void __init handle_block_event(struct HvLpEvent *event)
+{
+	struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
+	struct vio_waitevent *pwe;
+
+	if (event == NULL)
+		/* Notification that a partition went away! */
+		return;
+	/* First, we should NEVER get an int here...only acks */
+	if (hvlpevent_is_int(event)) {
+		printk(KERN_WARNING "handle_viod_request: "
+		       "Yikes! got an int in viodasd event handler!\n");
+		if (hvlpevent_need_ack(event)) {
+			event->xRc = HvLpEvent_Rc_InvalidSubtype;
+			HvCallEvent_ackLpEvent(event);
+		}
+		return;
+	}
+
+	switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+	case vioblockopen:
+		/*
+		 * Handle a response to an open request.  We get all the
+		 * disk information in the response, so update it.  The
+		 * correlation token contains a pointer to a waitevent
+		 * structure that has a completion in it.  update the
+		 * return code in the waitevent structure and post the
+		 * completion to wake up the guy who sent the request
+		 */
+		pwe = (struct vio_waitevent *)event->xCorrelationToken;
+		pwe->rc = event->xRc;
+		pwe->sub_result = bevent->sub_result;
+		complete(&pwe->com);
+		break;
+	case vioblockclose:
+		break;
+	default:
+		printk(KERN_WARNING "handle_viod_request: unexpected subtype!");
+		if (hvlpevent_need_ack(event)) {
+			event->xRc = HvLpEvent_Rc_InvalidSubtype;
+			HvCallEvent_ackLpEvent(event);
+		}
+	}
+}
+
+static void __init probe_disk(struct device_node *vio_root, u32 unit)
+{
+	HvLpEvent_Rc hvrc;
+	struct vio_waitevent we;
+	u16 flags = 0;
+
+retry:
+	init_completion(&we.com);
+
+	/* Send the open event to OS/400 */
+	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+			HvLpEvent_Type_VirtualIo,
+			viomajorsubtype_blockio | vioblockopen,
+			HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+			viopath_sourceinst(viopath_hostLp),
+			viopath_targetinst(viopath_hostLp),
+			(u64)(unsigned long)&we, VIOVERSION << 16,
+			((u64)unit << 48) | ((u64)flags<< 32),
+			0, 0, 0);
+	if (hvrc != 0) {
+		printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n",
+			(int)hvrc);
+		return;
+	}
+
+	wait_for_completion(&we.com);
+
+	if (we.rc != 0) {
+		if (flags != 0)
+			return;
+		/* try again with read only flag set */
+		flags = vioblockflags_ro;
+		goto retry;
+	}
+
+	/* Send the close event to OS/400.  We DON'T expect a response */
+	hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+			HvLpEvent_Type_VirtualIo,
+			viomajorsubtype_blockio | vioblockclose,
+			HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
+			viopath_sourceinst(viopath_hostLp),
+			viopath_targetinst(viopath_hostLp),
+			0, VIOVERSION << 16,
+			((u64)unit << 48) | ((u64)flags << 32),
+			0, 0, 0);
+	if (hvrc != 0) {
+		printk(KERN_WARNING "probe_disk: "
+		       "bad rc sending event to OS/400 %d\n", (int)hvrc);
+		return;
+	}
+
+	do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+			"block", "IBM,iSeries-viodasd", NULL);
+}
+
+static void __init get_viodasd_info(struct device_node *vio_root)
+{
+	int rc;
+	u32 unit;
+
+	rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2);
+	if (rc) {
+		printk(KERN_WARNING "get_viodasd_info: "
+		       "error opening path to host partition %d\n",
+		       viopath_hostLp);
+		return;
+	}
+
+	/* Initialize our request handler */
+	vio_setHandler(viomajorsubtype_blockio, handle_block_event);
+
+	for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
+		probe_disk(vio_root, unit);
+
+	vio_clearHandler(viomajorsubtype_blockio);
+	viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
+}
+
 static void __init handle_cd_event(struct HvLpEvent *event)
 {
 	struct viocdlpevent *bevent;
@@ -233,49 +430,9 @@ static void __init get_viocd_info(struct device_node *vio_root)
 
 	for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
 			unitinfo[unit].rsrcname[0]; unit++) {
-		struct device_node *np;
-		char name[64];
-		u32 reg = FIRST_VIOCD + unit;
-
-		snprintf(name, sizeof(name), "/vdevice/viocd@%08x", reg);
-		np = new_node(name, vio_root);
-		if (!np)
-			goto hv_free;
-		if (!add_string_property(np, "name", "viocd") ||
-			!add_string_property(np, "device_type", "block") ||
-			!add_string_property(np, "compatible",
-				"IBM,iSeries-viocd") ||
-			!add_raw_property(np, "reg", sizeof(reg), &reg) ||
-			!add_raw_property(np, "linux,unit_address",
-				sizeof(unit), &unit) ||
-			!add_raw_property(np, "linux,vio_rsrcname",
-				sizeof(unitinfo[unit].rsrcname),
-				unitinfo[unit].rsrcname) ||
-			!add_raw_property(np, "linux,vio_type",
-				sizeof(unitinfo[unit].type),
-				unitinfo[unit].type) ||
-			!add_raw_property(np, "linux,vio_model",
-				sizeof(unitinfo[unit].model),
-				unitinfo[unit].model))
-			goto node_free;
-		np->name = of_get_property(np, "name", NULL);
-		np->type = of_get_property(np, "device_type", NULL);
-		of_attach_node(np);
-#ifdef CONFIG_PROC_DEVICETREE
-		if (vio_root->pde) {
-			struct proc_dir_entry *ent;
-
-			ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
-					vio_root->pde);
-			if (ent)
-				proc_device_tree_add_node(np, ent);
-		}
-#endif
-		continue;
-
- node_free:
-		free_node(np);
-		break;
+		if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
+				"block", "IBM,iSeries-viocd", &unitinfo[unit]))
+			break;
 	}
 
  hv_free:
@@ -350,49 +507,10 @@ static void __init get_viotape_info(struct device_node *vio_root)
 
 	for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
 			unitinfo[unit].rsrcname[0]; unit++) {
-		struct device_node *np;
-		char name[64];
-		u32 reg = FIRST_VIOTAPE + unit;
-
-		snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
-		np = new_node(name, vio_root);
-		if (!np)
-			goto hv_free;
-		if (!add_string_property(np, "name", "viotape") ||
-			!add_string_property(np, "device_type", "byte") ||
-			!add_string_property(np, "compatible",
-				"IBM,iSeries-viotape") ||
-			!add_raw_property(np, "reg", sizeof(reg), &reg) ||
-			!add_raw_property(np, "linux,unit_address",
-				sizeof(unit), &unit) ||
-			!add_raw_property(np, "linux,vio_rsrcname",
-				sizeof(unitinfo[unit].rsrcname),
-				unitinfo[unit].rsrcname) ||
-			!add_raw_property(np, "linux,vio_type",
-				sizeof(unitinfo[unit].type),
-				unitinfo[unit].type) ||
-			!add_raw_property(np, "linux,vio_model",
-				sizeof(unitinfo[unit].model),
-				unitinfo[unit].model))
-			goto node_free;
-		np->name = of_get_property(np, "name", NULL);
-		np->type = of_get_property(np, "device_type", NULL);
-		of_attach_node(np);
-#ifdef CONFIG_PROC_DEVICETREE
-		if (vio_root->pde) {
-			struct proc_dir_entry *ent;
-
-			ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
-					vio_root->pde);
-			if (ent)
-				proc_device_tree_add_node(np, ent);
-		}
-#endif
-		continue;
-
- node_free:
-		free_node(np);
-		break;
+		if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
+				unit, "byte", "IBM,iSeries-viotape",
+				&unitinfo[unit]))
+			break;
 	}
 
  hv_free:
@@ -422,6 +540,7 @@ static int __init iseries_vio_init(void)
 			goto put_node;
 	}
 
+	get_viodasd_info(vio_root);
 	get_viocd_info(vio_root);
 	get_viotape_info(vio_root);
 
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index af3969a..e824b67 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -74,53 +74,9 @@ enum {
 static DEFINE_SPINLOCK(viodasd_spinlock);
 
 #define VIOMAXREQ		16
-#define VIOMAXBLOCKDMA		12
 
 #define DEVICE_NO(cell)	((struct viodasd_device *)(cell) - &viodasd_devices[0])
 
-struct open_data {
-	u64	disk_size;
-	u16	max_disk;
-	u16	cylinders;
-	u16	tracks;
-	u16	sectors;
-	u16	bytes_per_sector;
-};
-
-struct rw_data {
-	u64	offset;
-	struct {
-		u32	token;
-		u32	reserved;
-		u64	len;
-	} dma_info[VIOMAXBLOCKDMA];
-};
-
-struct vioblocklpevent {
-	struct HvLpEvent	event;
-	u32			reserved;
-	u16			version;
-	u16			sub_result;
-	u16			disk;
-	u16			flags;
-	union {
-		struct open_data	open_data;
-		struct rw_data		rw_data;
-		u64			changed;
-	} u;
-};
-
-#define vioblockflags_ro   0x0001
-
-enum vioblocksubtype {
-	vioblockopen = 0x0001,
-	vioblockclose = 0x0002,
-	vioblockread = 0x0003,
-	vioblockwrite = 0x0004,
-	vioblockflush = 0x0005,
-	vioblockcheck = 0x0007
-};
-
 struct viodasd_waitevent {
 	struct completion	com;
 	int			rc;
@@ -429,7 +385,7 @@ static void do_viodasd_request(struct request_queue *q)
  * Probe a single disk and fill in the viodasd_device structure
  * for it.
  */
-static void probe_disk(struct viodasd_device *d)
+static int probe_disk(struct viodasd_device *d)
 {
 	HvLpEvent_Rc hvrc;
 	struct viodasd_waitevent we;
@@ -453,14 +409,14 @@ retry:
 			0, 0, 0);
 	if (hvrc != 0) {
 		printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc);
-		return;
+		return 0;
 	}
 
 	wait_for_completion(&we.com);
 
 	if (we.rc != 0) {
 		if (flags != 0)
-			return;
+			return 0;
 		/* try again with read only flag set */
 		flags = vioblockflags_ro;
 		goto retry;
@@ -490,15 +446,32 @@ retry:
 	if (hvrc != 0) {
 		printk(VIOD_KERN_WARNING
 		       "bad rc sending event to OS/400 %d\n", (int)hvrc);
-		return;
+		return 0;
 	}
+
+	if (d->dev == NULL) {
+		/* this is when we reprobe for new disks */
+		if (vio_create_viodasd(dev_no) == NULL) {
+			printk(VIOD_KERN_WARNING
+				"cannot allocate virtual device for disk %d\n",
+				dev_no);
+			return 0;
+		}
+		/*
+		 * The vio_create_viodasd will have recursed into this
+		 * routine with d->dev set to the new vio device and
+		 * will finish the setup of the disk below.
+		 */
+		return 1;
+	}
+
 	/* create the request queue for the disk */
 	spin_lock_init(&d->q_lock);
 	q = blk_init_queue(do_viodasd_request, &d->q_lock);
 	if (q == NULL) {
 		printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n",
 				dev_no);
-		return;
+		return 0;
 	}
 	g = alloc_disk(1 << PARTITION_SHIFT);
 	if (g == NULL) {
@@ -506,7 +479,7 @@ retry:
 				"cannot allocate disk structure for disk %d\n",
 				dev_no);
 		blk_cleanup_queue(q);
-		return;
+		return 0;
 	}
 
 	d->disk = g;
@@ -538,6 +511,7 @@ retry:
 
 	/* register us in the global list */
 	add_disk(g);
+	return 1;
 }
 
 /* returns the total number of scatterlist elements converted */
@@ -718,8 +692,7 @@ static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
 	struct viodasd_device *d = &viodasd_devices[vdev->unit_address];
 
 	d->dev = &vdev->dev;
-	probe_disk(d);
-	if (d->disk == NULL)
+	if (!probe_disk(d))
 		return -ENODEV;
 	return 0;
 }
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index 2555dfd..f9ac0d0 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -51,6 +51,51 @@
  */
 #define VIO_MAX_SUBTYPES 8
 
+#define VIOMAXBLOCKDMA	12
+
+struct open_data {
+	u64	disk_size;
+	u16	max_disk;
+	u16	cylinders;
+	u16	tracks;
+	u16	sectors;
+	u16	bytes_per_sector;
+};
+
+struct rw_data {
+	u64	offset;
+	struct {
+		u32	token;
+		u32	reserved;
+		u64	len;
+	} dma_info[VIOMAXBLOCKDMA];
+};
+
+struct vioblocklpevent {
+	struct HvLpEvent	event;
+	u32			reserved;
+	u16			version;
+	u16			sub_result;
+	u16			disk;
+	u16			flags;
+	union {
+		struct open_data	open_data;
+		struct rw_data		rw_data;
+		u64			changed;
+	} u;
+};
+
+#define vioblockflags_ro   0x0001
+
+enum vioblocksubtype {
+	vioblockopen = 0x0001,
+	vioblockclose = 0x0002,
+	vioblockread = 0x0003,
+	vioblockwrite = 0x0004,
+	vioblockflush = 0x0005,
+	vioblockcheck = 0x0007
+};
+
 struct viocdlpevent {
 	struct HvLpEvent	event;
 	u32			reserved;
@@ -133,6 +178,8 @@ extern void vio_set_hostlp(void);
 extern void *vio_get_event_buffer(int subtype);
 extern void vio_free_event_buffer(int subtype, void *buffer);
 
+extern struct vio_dev *vio_create_viodasd(u32 unit);
+
 extern HvLpIndex viopath_hostLp;
 extern HvLpIndex viopath_ourLp;
 
-- 
1.5.3.2

^ permalink raw reply related

* Re: [PATCH 1/15] boot: find initrd location from device-tree
From: David Gibson @ 2007-09-24  2:58 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-01.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:03:24PM -0500, Milton Miller wrote:
> Some platforms have a boot agent that can create or modify properties in
> the device-tree and load images into memory.  Provide a helper to set
> loader_info used by prep_initrd().
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Acked-by: David Gibson <david@gibson.dropbear.id.au>

Hrm, despite my earlier ack, I'm going to whinge about a few nits
here.

> --- 
> re 12168
> rediffed types.h, offset in ops.h
> 
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-17 22:12:47.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h	2007-09-17 22:12:51.000000000 -0500
> @@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3
>  void __dt_fixup_mac_addresses(u32 startindex, ...);
>  #define dt_fixup_mac_addresses(...) \
>  	__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
> +void dt_find_initrd(void);
>  
>  
>  static inline void *find_node_by_linuxphandle(const u32 linuxphandle)
> Index: kernel/arch/powerpc/boot/types.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/types.h	2007-09-17 22:12:47.000000000 -0500
> +++ kernel/arch/powerpc/boot/types.h	2007-09-17 22:12:51.000000000 -0500
> @@ -12,6 +12,8 @@ typedef short			s16;
>  typedef int			s32;
>  typedef long long		s64;
>  
> +#define UINT_MAX	0xFFFFFFFF

I actually don't like this constant - at the point you compare you
care, explicitly, about the value not being over 32-bits, rather than
whether it fits a uint, so the named constant is more misleading than
helpful.

> +
>  #define min(x,y) ({ \
>  	typeof(x) _x = (x);	\
>  	typeof(y) _y = (y);	\
> Index: kernel/arch/powerpc/boot/devtree.c
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/devtree.c	2007-09-17 22:12:47.000000000 -0500
> +++ kernel/arch/powerpc/boot/devtree.c	2007-09-17 22:12:51.000000000 -0500
> @@ -1,6 +1,7 @@
>  /*
>   * devtree.c - convenience functions for device tree manipulation
>   * Copyright 2007 David Gibson, IBM Corporation.
> + * Copyright 2007 Milton Miller, IBM Corporation.
>   * Copyright (c) 2007 Freescale Semiconductor, Inc.
>   *
>   * Authors: David Gibson <david@gibson.dropbear.id.au>
> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const c
>  
>  	return 0;
>  }
> +
> +/**
> + * dt_find_initrd - set loader initrd location based on existing properties
> + *
> + * finds the linux,initrd-start and linux,initrd-end properties in
> + * the /chosen node and sets the loader initrd fields accordingly.
> + *
> + * Use this if your loader sets the properties to allow other code to
> + * relocate the tree and/or cause r3 and r4 to be set on true OF
> + * platforms.

I am unable to make sense of the paragraph above.

> + */
> +void dt_find_initrd(void)
> +{
> +	int rc;
> +	unsigned long long initrd_start, initrd_end;
> +	void *devp;
> +	static const char start_prop[] = "linux,initrd-start";
> +	static const char end_prop[] = "linux,initrd-end";

I think these constants are more obscuring than useful.

> +
> +	devp = finddevice("/chosen");
> +	if (! devp) {
> +		return;
> +	}

CodingStyle would not put { } here.

> +
> +	rc = getprop(devp, start_prop, &initrd_start, sizeof(initrd_start));
> +	if (rc < 0)
> +		return;				/* not found */
> +	/* The properties had to be 8 bytes until 2.6.22 */
> +	if (rc == sizeof(unsigned long)) {
> +		unsigned long tmp;
> +		memcpy(&tmp, &initrd_start, rc);
> +		initrd_start = tmp;
> +	} else if (rc != sizeof(initrd_start)) {	/* now they
> can be 4 */

Right.  8 bytes and 4 bytes, so you should be using explicit length
types instead of long and long long.

> +		printf("unexpected length of %s in /chosen!\n\r", start_prop);
> +		return;

All these printf() / return stanzas add a lot of verbosity to this
function.  Any way they can be consolidated a bit, maybe a single
error path that just prints the property values, so the user can
figure out what was wrong with them.

> +	}
> +
> +	rc = getprop(devp, end_prop, &initrd_end, sizeof(initrd_end));
> +	if (rc < 0) {
> +		printf("chosen has %s but no %s!\n\r", start_prop, end_prop);
> +		return;
> +	}
> +	if (rc == sizeof(unsigned long)) {
> +		unsigned long tmp;
> +		memcpy(&tmp, &initrd_end, rc);
> +		initrd_end = tmp;
> +	} else if (rc != sizeof(initrd_end)) {
> +		printf("unexpected length of %s in /chosen!\n\r", end_prop);
> +		return;
> +	}
> +
> +	/* Check for presence, ignore if (partially) loaded above 32 bits */
> +	if (initrd_start == initrd_end) {
> +		printf("ignoring empty device-tree supplied initrd\n");
> +	} else if (initrd_start > initrd_end) {
> +		printf("ignoring device-tree supplied initrd: start 0x%llx"
> +				" > end 0x%llx \n", initrd_start, initrd_end);
> +	} else if (initrd_end > UINT_MAX) {
> +		printf("ignoring device-tree supplied initrd:"
> +				" end 0x%llx > 32 bits\n", initrd_end);
> +	} else {
> +		loader_info.initrd_addr = initrd_start;
> +		loader_info.initrd_size  = initrd_end - initrd_start;
> +	}
> +}
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 2/15] boot: record header bytes in gunzip_start
From: David Gibson @ 2007-09-24  2:59 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-02.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:03:34PM -0500, Milton Miller wrote:
> 
> Record the number of header bytes skipped in the total bytes read field.
> 
> This is needed for the initramfs parsing code to find the end of the
> zip file.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 5/15] bootwrapper: occuppied memory ranges
From: David Gibson @ 2007-09-24  3:09 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-05.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:04:18PM -0500, Milton Miller wrote:
> Add a set of library routines to manage gross memory allocations.
> 
> This code uses an array in bss to store upto 32 entrys with merging
> representing a range of memory below rma_end (aka end of real mode
> memory at 0).
> 
> To use this code, a platform would set rma_end (find_rma_end), mark
> memory ranges occupied (add_known_ranges et al), initialize malloc in
> the spaces between (ranges_init_malloc), and optionally use the supplied
> vmlinux_alloc may be used.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> --- 
> vs 12172
> rename rmo_end to rma_end (real mode area, as used in papr)
> removed section labels (now in ops.h)
> rediff ops.h, Makefile
> moved find_rma_end here (from kexec.c in a later patch)
> find_rma_end searches by node type for "memory", checks that
> 	the parent is the root node, then looks for a reg property
> 	with the first address/size pair starting at 0.

Urg.  It's an awful lot of code for the bootwrapper.  Am I right in
understanding that the only reason to use the ranges code is for the
ranges based malloc() and vmlinux_alloc() you get out of it?

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 6/15] bootwrapper: help for 64 bit cpus
From: David Gibson @ 2007-09-24  3:14 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-06.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:04:37PM -0500, Milton Miller wrote:
> Add code to check if the processor is in 64 or 32 bit mode using
> only instructions from the 32 bit subset.  If the processor is in
> 64 bit mode, switch to 32 bit mode by clearing MSR[SF].
> 
> Also add a 64 bit procedure descriptor to use as a elf64 entry
> point.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> --- 
> vs 12173
> correct comment (equal vs not-equal)
> 
> Index: kernel/arch/powerpc/boot/crt0.S
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/crt0.S	2007-07-10 03:33:36.000000000 -0500
> +++ kernel/arch/powerpc/boot/crt0.S	2007-07-10 03:39:08.000000000 -0500
> @@ -17,11 +17,47 @@
>  _zimage_start_opd:
>  	.long	_zimage_start, 0, 0, 0
>  
> +	/* a procedure descriptor used when pretending to be elf64_powerpc */
> +	.balign	8
> +	.globl	_zimage_start_64
> +_zimage_start_64:

Hrm, I'd prefer _zimage_start_opd64 in analogy with the COFF opd entry
above.

> +	.long	0, _zimage_start	/* big endian, supported reloc ppc32 */
> +	.long	0, 0, 0, 0, 0, 0
> +
> +
>  	.weak	_zimage_start
>  	.globl	_zimage_start
>  _zimage_start:
>  	.globl	_zimage_start_lib
>  _zimage_start_lib:
> +	/* Check if the processor is running in 32 bit mode, using
> +	 * only 32 bit instructions which should be safe on 32 and
> +	 * 64 bit processors.
> +	 *
> +	 * Subtract bottom 32 bits of MSR from full value recording
> +	 * the result.  Since MSR[SF] is in the high word, we will
> +	 * be equal iff in 32 bit mode (either the processor is
> +	 * a 32 bit processor or MSR[SF] = 0).
> +	 */
> +	mfmsr	r0		/* grab whole msr		*/
> +	rlwinm	r8,r0,0,0,31	/* extract bottom word		*/
> +	subf.	r8,r8,r0	/* subtract, same?		*/
> +	beq	0f		/* yes: we are 32 bit mode	*/
> +
> +	/* We are in 64-bit mode.  This program must run in 32 bit
> +	 * mode.  Assume we are actually running somewhere in the
> +	 * low 32 bits of the address space, so we can just turn
> +	 * off MSR[SF] which is bit 0.
> +	 */
> +	.machine push
> +	.machine "ppc64"
> +	rldicl	r0,r0,0,1
> +	sync
> +	mtmsrd	r0
> +	isync
> +	.machine pop
> +0:	/* We are now in 32-bit mode */
> +
>  	/* Work out the offset between the address we were linked at
>  	   and the address where we're running. */
>  	bl	1f
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 7/15] bootwrapper: Add kexec callable zImage wrapper
From: David Gibson @ 2007-09-24  3:23 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-07.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:04:58PM -0500, Milton Miller wrote:
> 
> This code creates a 32 bit zImage wrapper for a 32 or 64 bit PowerPC
> Linux kernel.  This allows you to kexec a zImage with its compressed
> vmlinux instead of the uncompressed vmlinux elf.  The code is also
> packaged as a 64 bit elf for use by kexec-tools on 64 bit kernels.
> 
> Limitations:
> Note: the device-tree generated by kexec-tools is currently version 2,
> not the version 16 supported by the boot code base.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> find_rmo_end moved to memranges as find_rma_end.
> early_scan_flat_tree replaced with calls to its pieces in
> kexec_platform_init
> rediff wrapper, Makefile, ops.h
> 
> Index: kernel/arch/powerpc/boot/kexec.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/kexec.c	2007-09-21 04:52:46.000000000 -0500
> @@ -0,0 +1,122 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + * Copyright IBM Corporation 2007
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + */
> +
> +#include "ops.h"
> +#include "stdio.h"
> +#include "flatdevtree.h"
> +#include "page.h"
> +#include "types.h"
> +
> +extern char _start[];
> +extern char _end[];

Don't need these externs any more, they're in the headers.

> +
> +BSS_STACK(16*1024);
> +
> +static void find_console_from_tree(void)
> +{
> +	int rc = -1;
> +
> +	if (rc) {
> +		/* no console, oh well */
> +	}

Um... pointless function...?

> +}
> +
> +/**
> + * setup_initial_heap - setup a small heap in the bss
> + * Using a preallocated heap, setup for scanning the device tree.
> + * Intended for the initial read while the tree will remain read-only so
> + * a minimal malloc and search limit can be used.  This way we don't have
> + * lots of data or bss to clear.
> + */
> +static void setup_initial_heap(void)
> +{
> +	static char initial_heap[8*1024];
> +	void *heap_end;
> +
> +	heap_end = simple_alloc_init(initial_heap,
> +			sizeof(initial_heap) * 7 / 8,
> +			sizeof(long), 64);
> +
> +	if (heap_end - sizeof(initial_heap) > (void *)&initial_heap[0])
> +		fatal("Initial heap too big\n\r");
> +}
> +
> +static void init_flat_tree(struct boot_param_header *dt_blob)
> +{
> +	int rc;
> +
> +	rc = ft_init(dt_blob, dt_blob->totalsize, /* max_finddevice */ 1024);
> +	if (rc)
> +		fatal("Unable to initialize device_tree library!\n\r");
> +}
> +
> +static void *saved_vmlinux_addr;
> +
> +static void *kexec_vmlinux_alloc(unsigned long size)
> +{
> +	void *addr;
> +
> +	addr = ranges_vmlinux_alloc(size);
> +
> +	saved_vmlinux_addr = addr;
> +	return addr;
> +}
> +
> +static void kexec_fixups(void)
> +{
> +	wait_slaves_moved();
> +}
> +
> +static unsigned long (*finalize_chain)(void);
> +
> +static unsigned long kexec_finalize(void)
> +{
> +	send_slaves_to_kernel(saved_vmlinux_addr);

Ow, yuck, no.  The finalize callback is for finalizing the device
tree, don't abuse it for SMP entry.  It's a new thing that needs to be
done, so create a new callback for it.

> +
> +	return finalize_chain();
> +}
> +
> +void kexec_platform_init(struct boot_param_header *dt_blob)
> +{
> +	slaves_are_low();
> +	move_slaves_up();
> +
> +	setup_initial_heap();
> +	init_flat_tree(dt_blob);
> +	/*
> +	 * drivers can malloc and read the tree, but not realloc later
> +	 * or modify the tree now.
> +	 */
> +	if (!console_ops.write)
> +		find_console_from_tree();
> +
> +	find_rma_end();
> +	dt_find_initrd();
> +	add_known_ranges(dt_blob);
> +	ranges_init_malloc();
> +
> +	/* now that we have a malloc region, start over from the flat tree */
> +	init_flat_tree(dt_blob);
> +
> +	platform_ops.vmlinux_alloc = kexec_vmlinux_alloc;
> +	platform_ops.fixups = kexec_fixups;
> +	finalize_chain = dt_ops.finalize;
> +	dt_ops.finalize = kexec_finalize;
> +}
> Index: kernel/arch/powerpc/boot/crt0_kexec.S
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/crt0_kexec.S	2007-09-21 04:52:46.000000000 -0500
> @@ -0,0 +1,45 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + * Copyright 2007 IBM Corporation.
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + *
> + */
> +	/*
> +	 * The kernel calls out to the first image with
> +	 * r3 = boot cpu, r4 = entrypoint, r5 = 0
> +	 *
> +	 * kexec-tools purgatory calls this as it would a linux kernel:
> +	 * r3 = boot block, r4 = entrypoint, r5 = 0
> +	 *
> +	 * The boot block boot_cpu field has been filled in.
> +	 *
> +	 * kexec-tools and its purgatory are suppposed to copy SMP_SLAVE_SIZE
> +	 * bytes from the from entry point, but aparently instead it copies
> +	 * from the image start.
> +	 */
> +	.globl _zimage_start
> +_zimage_start:
> +
> +#include "marshal_low.S"
> +
> +	.globl	_zimage_start_plat
> +_zimage_start_plat:
> +	b	_zimage_start_lib
> +
> +	.globl	platform_init
> +platform_init:
> +	b	kexec_platform_init
> Index: kernel/arch/powerpc/boot/wrapper
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/wrapper	2007-09-21 04:51:31.000000000 -0500
> +++ kernel/arch/powerpc/boot/wrapper	2007-09-21 04:52:46.000000000 -0500
> @@ -133,6 +133,12 @@ coff)
>      platformo=$object/of.o
>      lds=$object/zImage.coff.lds
>      ;;
> +kexec)
> +    platformo=$object/crt0_kexec.o
> +    ;;
> +kexec64)
> +    platformo="-e _zimage_start_64 $object/crt0_kexec.o"

Arg. Again, just because it happens to fit is not a good reason to
abuse platformo - which, obviously enough, s meant to contain the .o
file for the platform - to also contain flags.

> +    ;;
>  miboot|uboot)
>      # miboot and U-boot want just the bare bits, not an ELF binary
>      ext=bin
> @@ -190,6 +196,9 @@ uboot)
>      fi
>      exit 0
>      ;;
> +kexec64)
> +    ${CROSS}objcopy -O elf64-powerpc $ofile
> +    ;;
>  esac
>  
>  addsec() {
> Index: kernel/arch/powerpc/boot/Makefile
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/Makefile	2007-09-21 04:52:44.000000000 -0500
> +++ kernel/arch/powerpc/boot/Makefile	2007-09-21 04:52:46.000000000 -0500
> @@ -42,12 +42,12 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
>  	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
>  
>  src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
> -		marshal.c memranges.c \
> +		marshal.c memranges.c kexec.c \
>  		ns16550.c serial.c simple_alloc.c div64.S util.S \
>  		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
>  		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
>  		cpm-serial.c stdlib.c
> -src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
> +src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \
>  		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
>  		ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
>  		cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c
> @@ -128,6 +128,9 @@ quiet_cmd_wrap	= WRAP    $@
>        cmd_wrap	=$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
>  		$(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
>  
> +kexec-$(CONFIG_PPC32)			+= zImage.kexec
> +kexec-$(CONFIG_PPC64)			+= zImage.kexec64
> +
>  image-$(CONFIG_PPC_PSERIES)		+= zImage.pseries
>  image-$(CONFIG_PPC_MAPLE)		+= zImage.pseries
>  image-$(CONFIG_PPC_IBM_CELL_BLADE)	+= zImage.pseries
> @@ -140,6 +143,7 @@ image-$(CONFIG_PPC_HOLLY)		+= zImage.hol
>  image-$(CONFIG_PPC_PRPMC2800)		+= zImage.prpmc2800
>  image-$(CONFIG_PPC_ISERIES)		+= zImage.iseries
>  image-$(CONFIG_DEFAULT_UIMAGE)		+= uImage
> +image-$(CONFIG_KEXEC)			+= $(kexec-y)
>  
>  ifneq ($(CONFIG_DEVICE_TREE),"")
>  image-$(CONFIG_PPC_8xx)			+= cuImage.8xx
> @@ -158,7 +162,7 @@ ifeq ($(CONFIG_PPC32),y)
>  image-$(CONFIG_PPC_PMAC)	+= zImage.coff zImage.miboot
>  endif
>  
> -initrd-  := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
> +initrd-  := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-) $(kexec-))
>  initrd-y := $(patsubst zImage%, zImage.initrd%, \
>  		$(patsubst treeImage%, treeImage.initrd%, $(image-y)))
>  initrd-y := $(filter-out $(image-y), $(initrd-y))
> @@ -227,7 +231,7 @@ install: $(CONFIGURE) $(addprefix $(obj)
>  
>  # anything not in $(targets)
>  clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
> -	otheros.bld
> +	otheros.bld $(kexec-)
>  
>  # clean up files cached by wrapper
>  clean-kernel := vmlinux.strip vmlinux.bin
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-21 04:52:44.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h	2007-09-21 04:52:46.000000000 -0500
> @@ -95,6 +95,7 @@ void move_slaves_here(void *where);
>  void send_slaves_to_kernel(void *vmlinux_addr);
>  void slaves_are_low(void);
>  void wait_slaves_moved(void);
> +void kexec_platform_init(struct boot_param_header *dt_blob);

This platform specific function should not poluute ops.h.

>  
>  int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
>  int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
From: David Gibson @ 2007-09-24  3:36 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-08.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
> kexec-tools still produces a version 2 device tree, while the
> libraries in the wrapper only support version 16 and later.
> 
> Add a routine to convert a v2 flat device tree to a v16 one inplace
> by inserting OF_DT_NOP and chomping full path.  Make space for new
> headers by moving and then chomping the OF_DT_NOPs.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> vs 12175
> Rediffed Makefile, ops, kexec.c
> 
> Index: kernel/arch/powerpc/boot/flatdevtree_conv.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/flatdevtree_conv.c	2007-09-20 17:49:04.000000000 -0500
> @@ -0,0 +1,280 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + * Copyright IBM Corporation 2007
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + */
> +#include "flatdevtree.h"
> +#include "stdio.h"
> +#include "ops.h"
> +
> +#define MIN_VERSION 2
> +#define OUT_VERSION 16

Should output version 17.  In any case, don't try to be so general -
just convert v123 (all basically the same) to latest (i.e. v17)
without all the #if nonsense.

> +#define OUT_COMPAT 16
> +
> +#ifdef NO_CHECK
> +static int check_v123_tree(u32 *start, u32 *limit)
> +{
> +	return 0;
> +}
> +#else
> +/**
> + * check_v123_tree - check integrety of a version 1, 2, or 3 tree
> + * @start: the start of the device tree struct
> + * @limit: the end of the region for the struct
> + * structural checks on device_tree
> + */
> +static int check_v123_tree(u32 *start, u32 *limit)

What is the point of this check?  If the device tree is corrupt, we're
stuffed anyway, so why bother?

> +{
> +	u32 len;
> +	int depth = 0;
> +	u32 *dtp = start;
> +
> +	while (dtp < limit)
> +		switch (*dtp) {
> +		case OF_DT_END:
> +			if (depth)
> +				return -1;
> +			return ++dtp - start;
> +		case OF_DT_NOP:
> +			dtp++;
> +			break;
> +		case OF_DT_END_NODE:
> +			dtp++;
> +			depth--;
> +			break;
> +		case OF_DT_BEGIN_NODE:
> +			len = strlen((char *)(++dtp));
> +			/* check path is suffix to previous? */
> +			dtp += 1 + (len / 4);
> +			depth++;
> +			break;
> +		case OF_DT_PROP:
> +			len = dtp[1];
> +			dtp += 3;
> +			if ((len >= 8) && ((long)dtp & 4))
> +				dtp++;
> +			dtp += (len + 3) / 4;
> +			break;
> +		default:
> +			return -1;
> +		}
> +	return -1;	/* no OF_DT_END */
> +}
> +#endif
> +
> +/**
> + * nop_to_v16 - add %OF_DT_NOP to hide alignment differences
> + * @dtp: pointer to the beginning of the struct area to modify
> + * insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 2, or 3.
> + */
> +static int nop_to_v16(u32 *dtp)
> +{
> +	int nops = 0;
> +	char *p, *s;
> +	int len;
> +	u32 *next;
> +
> +	while (*dtp != OF_DT_END)
> +		switch (*dtp) {
> +		case OF_DT_BEGIN_NODE:
> +			/* v2 & v3 names are full path, v16+ is relative */
> +			p = (char *)(++dtp);
> +			len = strlen(p);
> +			next = dtp + 1 + len / 4;
> +
> +			for (s = p + len; *s != '/'; s--)
> +				if (s == p)
> +					fatal("name %s has no '/'", p);
> +
> +			len -= s++ - p;		/* not the slash but the nul */
> +			memmove(p, s, len);
> +			while (len % 4)
> +				p[len++] = '\0';
> +			dtp += len / 4;
> +			while (dtp != next) {
> +				*dtp++ = OF_DT_NOP;
> +				nops++;
> +			}
> +			break;
> +		case OF_DT_PROP:
> +			/* convert from align_8 to align_4 via prefixing nop */
> +			len = dtp[1];
> +			if ((len >= 8) && !((long)dtp & 4)) {
> +				memmove(dtp+1, dtp, 12);
> +				*dtp++ = OF_DT_NOP;
> +				nops++;
> +			}
> +			dtp += 3 + (len + 3)/4;
> +			break;
> +		default:
> +			fatal("%s: unrecognised tag %d at %p\n", __FUNCTION__,
> +				*dtp, dtp);
> +		case OF_DT_NOP:
> +			nops ++;
> +			/* fall through */
> +		case OF_DT_END_NODE:
> +			dtp ++;
> +			break;
> +		}
> +	return nops;
> +}
> +
> +#if MIN_VERSION < 3 || OUT_VERSION > 16
> +/**
> + * move_nops_fwd - move nops in a v16 dt_struct to the beginning
> + * @start - device tree starting address
> + * @count - number of %OF_DT_NOP cells to move
> + */
> +static void move_nops_fwd(u32 *start, int count)

What on earth is the point of this.  The NOPs are perfectly valid
scattered within the tree, why go to all this trouble to shuffle them
about.

> +{
> +	u32 *dtp = start;
> +	int len;
> +	while (count)
> +		switch (*dtp) {
> +		case OF_DT_NOP:
> +			memmove(start+1,start,(dtp-start) * 4);
> +			*start++ = OF_DT_NOP;
> +			dtp++;
> +			count--;
> +			break;
> +		case OF_DT_END_NODE:
> +			dtp++;
> +			break;
> +		case OF_DT_BEGIN_NODE:
> +			len = strlen((char *)(++dtp));
> +			dtp += 1 + len / 4;
> +			break;
> +		case OF_DT_PROP:
> +			len = dtp[1];
> +			dtp += 3 + (len + 3) / 4;
> +			break;
> +		case OF_DT_END:
> +			fatal("Not enough nops -- need %d more\n", count);
> +			return;
> +		default:
> +			fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp)
> +		}
> +}
> +#endif
> +
> +/**
> + * conv_flattree_inplace upgrade the version of a boot_param_header
> + * @tree: pointer to the device tree header to convert
> + *
> + * Converts a v1, 2, 3 device tree (of at least MIN_VERSION)
> + * in place to OUT_VERSION (16) format, usable by flatdevtree.c
> + */
> +void conv_flattree_inplace(struct boot_param_header *tree)
> +{
> +	u32 *dtp;
> +	u32 need = 0, nops;
> +	int slen;
> +
> +	if (tree->magic != OF_DT_HEADER)
> +		fatal("%s: no magic", __FUNCTION__);

More pointless tests...

> +	if (tree->last_comp_version > 3)
> +		return;			/* don't know what to do */

Rather, don't need to do anything.

> +
> +	if (tree->version < MIN_VERSION) {
> +		printf("%s: Warning: can't handle version %d tree\n",
> +				__FUNCTION__, tree->version);
> +		return;
> +	}
> +
> +	if (tree->version < 2)
> +		need++;		/* boot_cpu_id */
> +
> +	if (tree->version < 3)
> +		need++;		/* dt_string_size */
> +
> +	if (OUT_VERSION > 16)
> +		need++;		/* dt_struct_size */
> +
> +	dtp = (void *)tree + tree->off_dt_struct;
> +
> +	slen = check_v123_tree(dtp, (void *)tree + tree->totalsize);
> +	if (slen < 0)
> +		fatal("device tree check failed\n");
> +
> +	nops = nop_to_v16(dtp);
> +
> +	if (need & 1)		/* keep 8 byte alignment of mem reserve */
> +		need++;
> +
> +	if (need > nops)
> +		fatal("Didn't find enough space to add new header fields\n\r"
> +			"(needed %d found %d tree %p)", need, nops, tree);
> +
> +	/* ok now compress the dtb struct */
> +	move_nops_fwd(dtp, need);
> +	dtp += need;
> +
> +	/*
> +	 * move mem_rsvmap and dt_strings if they are before dt_struct
> +	 * onto our nops .  Adjust start addresses for the 3 sections.
> +	 */

Hrm.  Do we really need to worry about this case.  You may be
producing v2 trees in kexec-tools, but do they actually have the
blocks out of order?  dtc certainly never produced them that way.

> +	if ((tree->off_mem_rsvmap < tree->off_dt_struct) ||
> +		(tree->off_dt_strings < tree->off_dt_struct)) {
> +		int start, end;
> +		void *ptr;
> +
> +		if (tree->off_mem_rsvmap < tree->off_dt_strings)
> +			start = tree->off_mem_rsvmap;
> +		else
> +			start = tree->off_dt_strings;
> +
> +		end = tree->off_dt_struct;
> +		ptr = (void *)tree + start;
> +
> +		memmove(ptr + 4 * need, ptr, end - start);
> +
> +		if (tree->off_mem_rsvmap < tree->off_dt_struct)
> +			tree->off_mem_rsvmap += 4 * need;
> +		if (tree->off_dt_strings < tree->off_dt_struct)
> +			tree->off_dt_strings += 4 * need;
> +	}
> +	tree->off_dt_struct += 4 * need;
> +
> +	/* ok now we have space to extend the header. */
> +	if (tree->version < 2 && MIN_VERSION < 2) {
> +		tree->boot_cpuid_phys = 0;	/* default, caller can fix */
> +	}
> +
> +	/* calculate size of dt_strings_size */
> +	if (tree->version < 3 && MIN_VERSION < 3) {
> +		int end = tree->totalsize;
> +
> +		if (tree->off_dt_strings < tree->off_mem_rsvmap)
> +			end = tree->off_mem_rsvmap;
> +
> +		if ((tree->off_dt_strings < tree->off_dt_struct) &&
> +				(end > tree->off_dt_struct))
> +			end = tree->off_dt_struct;
> +
> +		tree->dt_strings_size = end - tree->off_dt_strings;
> +	}
> +
> +#if OUT_VERSION > 16
> +	tree->dt_struct_size = 4 * slen;
> +#endif
> +
> +	tree->version = OUT_VERSION;
> +	tree->last_comp_version = OUT_COMPAT;
> +
> +	return;
> +}
> Index: kernel/arch/powerpc/boot/Makefile
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/Makefile	2007-09-20 17:42:24.000000000 -0500
> +++ kernel/arch/powerpc/boot/Makefile	2007-09-20 17:49:04.000000000 -0500
> @@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
>  	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
>  
>  src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
> -		marshal.c memranges.c kexec.c \
> +		flatdevtree_conv.c marshal.c memranges.c kexec.c \
>  		ns16550.c serial.c simple_alloc.c div64.S util.S \
>  		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
>  		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-20 17:42:24.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h	2007-09-20 17:49:04.000000000 -0500
> @@ -81,7 +81,10 @@ struct loader_info {
>  };
>  extern struct loader_info loader_info;
>  
> +struct boot_param_header;
> +
>  void start(void);
> +void conv_flattree_inplace(struct boot_param_header *tree);
>  int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
>  int serial_console_init(void);
>  int ns16550_console_init(void *devp, struct serial_console_data *scdp);
> Index: kernel/arch/powerpc/boot/kexec.c
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/kexec.c	2007-09-20 17:42:24.000000000 -0500
> +++ kernel/arch/powerpc/boot/kexec.c	2007-09-20 17:49:04.000000000 -0500
> @@ -99,6 +99,7 @@ void kexec_platform_init(struct boot_par
>  	move_slaves_up();
>  
>  	setup_initial_heap();
> +	conv_flattree_inplace(dt_blob);
>  	init_flat_tree(dt_blob);
>  	/*
>  	 * drivers can malloc and read the tree, but not realloc later
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 9/15] bootwrapper: rtas support
From: David Gibson @ 2007-09-24  3:46 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-09.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:05:30PM -0500, Milton Miller wrote:
> This code provides a console write that calls put-term-char.
> 
> To avoid PIC relocation of the absolute rtas addresses, hide the
> actual call to rtas in assembly and declare all variables as int.
> 
> An instantiated rtas will be protected by a reserved range in the
> device tree, so no explicit call to add_occupied_range is needed
> here.
> 
> Signed-off-by: Milton Miller <miltonm@bga.com>
> --- 
> vs 12176
> rtas_put_term_write now takes const char *buf
> rediff ops.h, Makefile
> 
> Index: kernel/arch/powerpc/boot/rtas.c
> ===================================================================
> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/rtas.c	2007-09-21 01:43:08.000000000 -0500
> @@ -0,0 +1,146 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
> + *
> + * Copyright 2007 IBM Corporation.
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + *
> + */
> +
> +#include "ops.h"
> +#include "stdio.h"
> +#include "flatdevtree.h"
> +
> +static int rtas_entry;
> +static int rtas_base;
> +static int rtas_size;
> +
> +static void find_rtas(void)
> +{
> +	int rc;
> +	void *devp;
> +	char *str;
> +
> +	devp = finddevice("/rtas");
> +	if (! devp)
> +		return;
> +
> +	str = "linux,rtas-entry";

wtf?  Just use the literals in the getprop() calls, this is pure
obfuscation.

> +	rc = getprop(devp, str, &rtas_entry, sizeof(rtas_entry));
> +	if (rc < 0)
> +		return;
> +	if (rc != sizeof(rtas_entry))
> +		goto fail;
> +
> +	str = "rtas-size";
> +	rc = getprop(devp, str, &rtas_size, sizeof(rtas_size));
> +	if (rc < 0)
> +		return;
> +	if (rc != sizeof(rtas_size))
> +		goto fail;
> +
> +	str = "linux,rtas-base";
> +	rc = getprop(devp, str, &rtas_base, sizeof(rtas_base));
> +	if (rc < 0) {
> +		printf("rtas-size but no linux,rtas-base in /rtas.  "
> +			"disabling wrapper rtas interface\n\r");
> +		rtas_entry = 0;
> +		return;
> +	}
> +
> +	if (rc != sizeof(rtas_base))
> +		goto fail;
> +
> +	return;
> +
> +
> +fail:
> +	printf("Unexpected length %d of %s property in /rtas.\n\r"
> +			"disabling wrapper rtas interface\n\r", rc, str);
> +	rtas_entry = 0;
> +	return;
> +}
> +
> +/*
> + * PIC relocation of function pointers happens at call time.
> + * We have an absolute out-of-image address.   So tell C they
> + * are just integers, and hide the call as an out-of-file
> + * function.
> + */

I don't get this.  If we can call into the kernel using a function
pointer, you should be able to call into rtas without this weirdness.

> +__asm__ (
> +		"	.globl call_rtas\n"
> +		"	call_rtas: mtctr 5\n"
> +		"	bctr\n"
> +		);
> +
> +void call_rtas(int args[], int base, int entry);
> +
> +
> +static int put_term_char;
> +
> +static void rtas_put_term_write(const char *buf, int len)
> +{
> +	int i, args[5];
> +
> +	args[0] = put_term_char;
> +	args[1] = 1;	/* num inputs */
> +	args[2] = 1;	/* num outputs */
> +
> +	for (i=0; i < len; ) {
> +		args[3] = buf[i];
> +		args[4] = 0;
> +
> +		call_rtas(args, rtas_base, rtas_entry);
> +		if (args[4] == 0)		/* SUCCESS */
> +			i++;
> +		else if (args[4] == -1)		/* HARDWARE_ERROR */
> +			break;
> +		/* else retry */
> +	}
> +}
> +
> +int rtas_console_init(void)
> +{
> +	void *devp;
> +	int rc;
> +
> +
> +	devp = finddevice("/rtas");
> +	if (!devp)
> +		return -1;
> +
> +	if (!rtas_entry)
> +		find_rtas();
> +	if (!rtas_entry)
> +		return -1;
> +
> +	rc = getprop(devp, "put-term-char", &put_term_char,
> +			sizeof(put_term_char));
> +	if (rc == sizeof(put_term_char))
> +		console_ops.write = rtas_put_term_write;
> +	else
> +		put_term_char = -1;
> +
> +	return put_term_char == -1 ? -1 : 0;
> +}
> +
> +/* for debug, hard code */
> +void use_rtas_console(int entry, int base, int tc)
> +{
> +	rtas_entry = entry;
> +	rtas_base = base;
> +	put_term_char = tc;
> +	console_ops.write = rtas_put_term_write;
> +}
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-21 01:43:02.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h	2007-09-21 01:43:08.000000000 -0500
> @@ -99,6 +99,8 @@ void send_slaves_to_kernel(void *vmlinux
>  void slaves_are_low(void);
>  void wait_slaves_moved(void);
>  void kexec_platform_init(struct boot_param_header *dt_blob);
> +int rtas_console_init(void);
> +void use_rtas_console(int entry, int base, int tc);
>  
>  int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
>  int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
> Index: kernel/arch/powerpc/boot/kexec.c
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/kexec.c	2007-09-21 01:43:02.000000000 -0500
> +++ kernel/arch/powerpc/boot/kexec.c	2007-09-21 01:43:08.000000000 -0500
> @@ -33,6 +33,9 @@ static void find_console_from_tree(void)
>  {
>  	int rc = -1;
>  
> +	rc = rtas_console_init();
> +	if (!rc)
> +		return;
>  	if (rc) {
>  		/* no console, oh well */
>  	}
> Index: kernel/arch/powerpc/boot/Makefile
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/Makefile	2007-09-21 01:43:02.000000000 -0500
> +++ kernel/arch/powerpc/boot/Makefile	2007-09-21 01:43:08.000000000 -0500
> @@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
>  	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
>  
>  src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
> -		flatdevtree_conv.c marshal.c memranges.c kexec.c \
> +		flatdevtree_conv.c marshal.c memranges.c kexec.c rtas.c \
>  		ns16550.c serial.c simple_alloc.c div64.S util.S \
>  		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
>  		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 1/2] qemu platform, v2
From: David Gibson @ 2007-09-24  4:00 UTC (permalink / raw)
  To: Christoph Hellwig
  Cc: linuxppc-dev, Paul Mackerras, Rob Landley, Milton Miller
In-Reply-To: <20070922095546.GA14185@lst.de>

On Sat, Sep 22, 2007 at 11:55:46AM +0200, Christoph Hellwig wrote:
> On Fri, Sep 21, 2007 at 06:08:31PM -0500, Milton Miller wrote:
> > Here is the second rev of patches to boot a arch powerpc kernel on
> > qemu with the prep architecture.
> 
> So if this is supposed to be prep why do you need additional kernel
> support?  And if you really needed why isn't it under
> platforms/prep?

Basically because PReP support doesn't work under arch/powerpc.
Getting it working properly is something that should happen, but will
take a while.  In the meantime, getting something that's sufficient to
get working under just qemu's version of prep, without using the
abominable openhackware is a quicker path to a usable arch/powerpc
kernel under qemu.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 13/15] bootwrapper: attach an empty vmlinux
From: David Gibson @ 2007-09-24  4:03 UTC (permalink / raw)
  To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-13.miltonm@bga.com>

On Fri, Sep 21, 2007 at 06:06:38PM -0500, Milton Miller wrote:
> Allow the boot wrapper code to be linked without an attached vmlinux.
> 
> Rather than invent a new syntax to invoke the wrapper, attach the
> stripped version of empty.o, which produces the same result.

Aiee.  Please don't do that.  Add a new wrapper option so the vmlinux
is optional instead.  

Particularly since...
> Index: kernel/arch/powerpc/boot/wrapper
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/wrapper	2007-09-17 22:11:51.000000000 -0500
> +++ kernel/arch/powerpc/boot/wrapper	2007-09-17 22:12:05.000000000 -0500
> @@ -161,6 +161,13 @@ ps3)
>      ;;
>  esac
>  
> +if [ "$kernel" = $object/empty.o ] ; then
> +    ext=bin
> +    objflags="-O binary"
> +    gzip=
> +fi

Making the vmlinux empty.o *isn't* just a matter of doing that but
also has other side effects as above.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: David Gibson @ 2007-09-24  5:07 UTC (permalink / raw)
  To: Peter Korsgaard; +Cc: linuxppc-dev, Timur Tabi
In-Reply-To: <874pholbdk.fsf@macbook.be.48ers.dk>

On Fri, Sep 21, 2007 at 09:35:03AM +0200, Peter Korsgaard wrote:
> >>>>> "Scott" == Scott Wood <scottwood@freescale.com> writes:
> 
> Hi,
> 
>  Scott> #size-cells is zero on i2c, so it should just be reg = <68>.
> 
>  Scott> You'll probably need to add #address-cells and #size-cells to the
>  Scott> controller node, as well.

Uh.. yes.. i2c interfaces should really always have #a and #s.

> Ahh - Thanks. This should be better.
> ---
> 
> [PATCH] mpc8349emitx.dts: Add ds1339 RTC
> 
> Add ds1339 I2C RTC chip as child of 2nd I2C controller.
> 
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
> ---
>  arch/powerpc/boot/dts/mpc8349emitx.dts |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> Index: linux/arch/powerpc/boot/dts/mpc8349emitx.dts
> ===================================================================
> --- linux.orig/arch/powerpc/boot/dts/mpc8349emitx.dts
> +++ linux/arch/powerpc/boot/dts/mpc8349emitx.dts
> @@ -62,12 +62,21 @@
>  		};
>  
>  		i2c@3100 {
> +			#address-cells = <1>;
> +			#size-cells = <0>;
>  			device_type = "i2c";

Hrm... we probably want an "i2c" device_type class, but I don't think
we've actually defined one, which is a problem

>  			compatible = "fsl-i2c";
>  			reg = <3100 100>;
>  			interrupts = <f 8>;
>  			interrupt-parent = < &ipic >;
>  			dfsrr;
> +
> +			rtc@68 {
> +				device_type = "rtc";
> +				compatible = "dallas,ds1339";
> +				reg = <68>;
> +			};

I think we want to think a bit more carefully about how to do bindings
for RTC devices.  No "rtc" device_type is defined, but again we might
want to.

I did find one real OF binding for a different Dallas RTC (and NVRAM),
see:

http://playground.sun.com/1275/proposals/Closed/Remanded/Accepted/346-it.txt

It's a little different from the example above.

The fact that NVRAM+RTC chips are so common is a bit of an issue from
the point of view of defining a device class binding - a device can't
have type "rtc" and "nvram".

> +
>  		};
>  
>  		spi@7000 {
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

^ permalink raw reply

* Re: [PATCH 1/15] boot: find initrd location from device-tree
From: Rob Landley @ 2007-09-24  5:50 UTC (permalink / raw)
  To: David Gibson; +Cc: linuxppc-dev, Paul Mackerras, Milton Miller
In-Reply-To: <20070924025824.GD8058@localhost.localdomain>

On Sunday 23 September 2007 9:58:24 pm David Gibson wrote:
> On Fri, Sep 21, 2007 at 06:03:24PM -0500, Milton Miller wrote:
> > Some platforms have a boot agent that can create or modify properties in
> > the device-tree and load images into memory.  Provide a helper to set
> > loader_info used by prep_initrd().
> >
> > Signed-off-by: Milton Miller <miltonm@bga.com>
> > Acked-by: David Gibson <david@gibson.dropbear.id.au>
>
> Hrm, despite my earlier ack, I'm going to whinge about a few nits
> here.
>
> > ---
> > re 12168
> > rediffed types.h, offset in ops.h
> >
> > Index: kernel/arch/powerpc/boot/ops.h
> > ===================================================================
> > --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-17 22:12:47.000000000
> > -0500 +++ kernel/arch/powerpc/boot/ops.h	2007-09-17 22:12:51.000000000
> > -0500 @@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3
> >  void __dt_fixup_mac_addresses(u32 startindex, ...);
> >  #define dt_fixup_mac_addresses(...) \
> >  	__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
> > +void dt_find_initrd(void);
> >
> >
> >  static inline void *find_node_by_linuxphandle(const u32 linuxphandle)
> > Index: kernel/arch/powerpc/boot/types.h
> > ===================================================================
> > --- kernel.orig/arch/powerpc/boot/types.h	2007-09-17 22:12:47.000000000
> > -0500 +++ kernel/arch/powerpc/boot/types.h	2007-09-17 22:12:51.000000000
> > -0500 @@ -12,6 +12,8 @@ typedef short			s16;
> >  typedef int			s32;
> >  typedef long long		s64;
> >
> > +#define UINT_MAX	0xFFFFFFFF
>
> I actually don't like this constant - at the point you compare you
> care, explicitly, about the value not being over 32-bits, rather than
> whether it fits a uint, so the named constant is more misleading than
> helpful.

Except int and uint are 32 bits on all targets, due to unix standardizing on 
LP64:

http://www.unix.org/whitepapers/64bit.html
http://www.unix.org/version2/whatsnew/lp64_wp.html

> > +/**
> > + * dt_find_initrd - set loader initrd location based on existing
> > properties + *
> > + * finds the linux,initrd-start and linux,initrd-end properties in
> > + * the /chosen node and sets the loader initrd fields accordingly.
> > + *
> > + * Use this if your loader sets the properties to allow other code to
> > + * relocate the tree and/or cause r3 and r4 to be set on true OF
> > + * platforms.
>
> I am unable to make sense of the paragraph above.

I think this means it finds the initrd location from the device tree (supplied 
by your firmware or bootloader) rather than from the kernel command line the 
way all the other platforms do.

Rob
-- 
"One of my most productive days was throwing away 1000 lines of code."
  - Ken Thompson.

^ permalink raw reply

* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: Peter Korsgaard @ 2007-09-24  5:52 UTC (permalink / raw)
  To: Scott Wood; +Cc: linuxppc-dev, Timur Tabi
In-Reply-To: <20070924050709.GM8058@localhost.localdomain>

>>>>> "David" == David Gibson <david@gibson.dropbear.id.au> writes:

Hi

 >> compatible = "fsl-i2c";
 >> reg = <3100 100>;
 >> interrupts = <f 8>;
 >> interrupt-parent = < &ipic >;
 >> dfsrr;
 >> +
 >> +			rtc@68 {
 >> +				device_type = "rtc";
 >> +				compatible = "dallas,ds1339";
 >> +				reg = <68>;
 >> +			};

 David> I think we want to think a bit more carefully about how to do bindings
 David> for RTC devices.  No "rtc" device_type is defined, but again we might
 David> want to.

Could be. I've simply done it like kuroboxHD.dts already does and
fsl_soc.c expects.

 David> I did find one real OF binding for a different Dallas RTC (and NVRAM),
 David> see:

 David> http://playground.sun.com/1275/proposals/Closed/Remanded/Accepted/346-it.txt

 David> It's a little different from the example above.

 David> The fact that NVRAM+RTC chips are so common is a bit of an issue from
 David> the point of view of defining a device class binding - a device can't
 David> have type "rtc" and "nvram".

True. I think we should primarily focus on the RTC part rather than
NVRAM as that's the "main" functionality and leave a NVRAM class for
I2C EEPROMs.

The Linux driver for the chip (rtc-1307.c) doesn't expose the NVRAM
bytes either.

But I'm open for suggestions.

-- 
Bye, Peter Korsgaard

^ permalink raw reply

* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: Kumar Gala @ 2007-09-24  6:13 UTC (permalink / raw)
  To: David Gibson; +Cc: Timur Tabi, linuxppc-dev
In-Reply-To: <20070924050709.GM8058@localhost.localdomain>


On Sep 24, 2007, at 12:07 AM, David Gibson wrote:

> On Fri, Sep 21, 2007 at 09:35:03AM +0200, Peter Korsgaard wrote:
>>>>>>> "Scott" == Scott Wood <scottwood@freescale.com> writes:
>>
>> Hi,
>>
>>  Scott> #size-cells is zero on i2c, so it should just be reg = <68>.
>>
>>  Scott> You'll probably need to add #address-cells and #size-cells  
>> to the
>>  Scott> controller node, as well.
>
> Uh.. yes.. i2c interfaces should really always have #a and #s.
>
>> Ahh - Thanks. This should be better.
>> ---
>>
>> [PATCH] mpc8349emitx.dts: Add ds1339 RTC
>>
>> Add ds1339 I2C RTC chip as child of 2nd I2C controller.
>>
>> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
>> ---
>>  arch/powerpc/boot/dts/mpc8349emitx.dts |    9 +++++++++
>>  1 file changed, 9 insertions(+)
>>
>> Index: linux/arch/powerpc/boot/dts/mpc8349emitx.dts
>> ===================================================================
>> --- linux.orig/arch/powerpc/boot/dts/mpc8349emitx.dts
>> +++ linux/arch/powerpc/boot/dts/mpc8349emitx.dts
>> @@ -62,12 +62,21 @@
>>  		};
>>
>>  		i2c@3100 {
>> +			#address-cells = <1>;
>> +			#size-cells = <0>;
>>  			device_type = "i2c";
>
> Hrm... we probably want an "i2c" device_type class, but I don't think
> we've actually defined one, which is a prob

suggestions on how to handle this?  We've described that fsl-i2c  
nodes in booting-without-of.txt should have it. (which may have been  
wrong at the time).

- k

>
>>  			compatible = "fsl-i2c";
>>  			reg = <3100 100>;
>>  			interrupts = <f 8>;
>>  			interrupt-parent = < &ipic >;
>>  			dfsrr;

^ permalink raw reply

* Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
From: Milton Miller @ 2007-09-24  6:54 UTC (permalink / raw)
  To: David Gibson; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <20070924033612.GI8058@localhost.localdomain>


On Sep 23, 2007, at 10:36 PM, David Gibson wrote:

> On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
>> kexec-tools still produces a version 2 device tree, while the
>> libraries in the wrapper only support version 16 and later.
>>
>> Add a routine to convert a v2 flat device tree to a v16 one inplace
>> by inserting OF_DT_NOP and chomping full path.  Make space for new
>> headers by moving and then chomping the OF_DT_NOPs.
>>
>> Signed-off-by: Milton Miller <miltonm@bga.com>
>> ---
>> vs 12175
>> Rediffed Makefile, ops, kexec.c
>>
>> Index: kernel/arch/powerpc/boot/flatdevtree_conv.c
>> ===================================================================
>> --- /dev/null	1970-01-01 00:00:00.000000000 +0000
>> +++ kernel/arch/powerpc/boot/flatdevtree_conv.c	2007-09-20 
>> 17:49:04.000000000 -0500
>> @@ -0,0 +1,280 @@
>> +/*
>> + * 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.
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
>> + * GNU General Public License for more details.
>> + *
>> + * You should have received a copy of the GNU General Public License
>> + * along with this program; if not, write to the Free Software
>> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA  
>> 02110-1301, USA.
>> + *
>> + * Copyright IBM Corporation 2007
>> + *
>> + * Authors: Milton Miller <miltonm@bga.com>
>> + */
>> +#include "flatdevtree.h"
>> +#include "stdio.h"
>> +#include "ops.h"
>> +
>> +#define MIN_VERSION 2
>> +#define OUT_VERSION 16
>
> Should output version 17.  In any case, don't try to be so general -
> just convert v123 (all basically the same) to latest (i.e. v17)
> without all the #if nonsense.

Outputing v17 instead of 16 requires more words to be added to the 
header, and the library does fine with v16.  Actually the v1 trees has 
some other differences such as initrd addresses were kernel linear not 
real, cpus were assigned logical numbers  ... so while the structure 
didn't change except for the header field, the contents did.  Actually, 
when converting v3 to v16 some of the code issn't needed, the ifs allow 
the code size to be reduced.

>
>> +#define OUT_COMPAT 16
>> +
>> +#ifdef NO_CHECK
>> +static int check_v123_tree(u32 *start, u32 *limit)
>> +{
>> +	return 0;
>> +}
>> +#else
>> +/**
>> + * check_v123_tree - check integrety of a version 1, 2, or 3 tree
>> + * @start: the start of the device tree struct
>> + * @limit: the end of the region for the struct
>> + * structural checks on device_tree
>> + */
>> +static int check_v123_tree(u32 *start, u32 *limit)
>
> What is the point of this check?  If the device tree is corrupt, we're
> stuffed anyway, so why bother?

Hence the ifdef NO_CHECK.   When developing, sometimes its nice to know 
if its your input or your program.  These functions are destructive to 
an improperlly formed tree, and in non-obvious ways.  When debugging, 
it's not hard to hardcode console write or read the printf string 
buffer with a hardware debugger to see error messages.  That said, it 
could be removed.

>
>> +{
>> +	u32 len;
>> +	int depth = 0;
>> +	u32 *dtp = start;
>> +
>> +	while (dtp < limit)
>> +		switch (*dtp) {
>> +		case OF_DT_END:
>> +			if (depth)
>> +				return -1;
>> +			return ++dtp - start;
>> +		case OF_DT_NOP:
>> +			dtp++;
>> +			break;
>> +		case OF_DT_END_NODE:
>> +			dtp++;
>> +			depth--;
>> +			break;
>> +		case OF_DT_BEGIN_NODE:
>> +			len = strlen((char *)(++dtp));
>> +			/* check path is suffix to previous? */
>> +			dtp += 1 + (len / 4);
>> +			depth++;
>> +			break;
>> +		case OF_DT_PROP:
>> +			len = dtp[1];
>> +			dtp += 3;
>> +			if ((len >= 8) && ((long)dtp & 4))
>> +				dtp++;
>> +			dtp += (len + 3) / 4;
>> +			break;
>> +		default:
>> +			return -1;
>> +		}
>> +	return -1;	/* no OF_DT_END */
>> +}
>> +#endif
>> +
>> +/**
>> + * nop_to_v16 - add %OF_DT_NOP to hide alignment differences
>> + * @dtp: pointer to the beginning of the struct area to modify
>> + * insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 
>> 2, or 3.
>> + */
>> +static int nop_to_v16(u32 *dtp)
>> +{
>> +	int nops = 0;
>> +	char *p, *s;
>> +	int len;
>> +	u32 *next;
>> +
>> +	while (*dtp != OF_DT_END)
>> +		switch (*dtp) {
>> +		case OF_DT_BEGIN_NODE:
>> +			/* v2 & v3 names are full path, v16+ is relative */
>> +			p = (char *)(++dtp);
>> +			len = strlen(p);
>> +			next = dtp + 1 + len / 4;
>> +
>> +			for (s = p + len; *s != '/'; s--)
>> +				if (s == p)
>> +					fatal("name %s has no '/'", p);
>> +
>> +			len -= s++ - p;		/* not the slash but the nul */
>> +			memmove(p, s, len);
>> +			while (len % 4)
>> +				p[len++] = '\0';
>> +			dtp += len / 4;
>> +			while (dtp != next) {
>> +				*dtp++ = OF_DT_NOP;
>> +				nops++;
>> +			}
>> +			break;
>> +		case OF_DT_PROP:
>> +			/* convert from align_8 to align_4 via prefixing nop */
>> +			len = dtp[1];
>> +			if ((len >= 8) && !((long)dtp & 4)) {
>> +				memmove(dtp+1, dtp, 12);
>> +				*dtp++ = OF_DT_NOP;
>> +				nops++;
>> +			}
>> +			dtp += 3 + (len + 3)/4;
>> +			break;
>> +		default:
>> +			fatal("%s: unrecognised tag %d at %p\n", __FUNCTION__,
>> +				*dtp, dtp);
>> +		case OF_DT_NOP:
>> +			nops ++;
>> +			/* fall through */
>> +		case OF_DT_END_NODE:
>> +			dtp ++;
>> +			break;
>> +		}
>> +	return nops;
>> +}
>> +
>> +#if MIN_VERSION < 3 || OUT_VERSION > 16
>> +/**
>> + * move_nops_fwd - move nops in a v16 dt_struct to the beginning
>> + * @start - device tree starting address
>> + * @count - number of %OF_DT_NOP cells to move
>> + */
>> +static void move_nops_fwd(u32 *start, int count)
>
> What on earth is the point of this.  The NOPs are perfectly valid
> scattered within the tree, why go to all this trouble to shuffle them
> about.

And if you notice, there is a "how many to move" argument.  The point 
of moving them to the front of the tree is the v17 device tree header 
takes more space than the v3 one, and the v2 header is smaller than 
both v17 and v16 header.  Since I am converting the tree in place, the 
space has to come from somewhere.  Since we are pretty much guaranteed 
to get several nops, this function moves them forward so they can be 
overwritten.  In practice we move 1-3 NOPS from the early properties > 
8 bytes and early grandchild nodes (eg /cpus/PowerPC,xxx).

>
>> +{
>> +	u32 *dtp = start;
>> +	int len;
>> +	while (count)
>> +		switch (*dtp) {
>> +		case OF_DT_NOP:
>> +			memmove(start+1,start,(dtp-start) * 4);
>> +			*start++ = OF_DT_NOP;
>> +			dtp++;
>> +			count--;
>> +			break;
>> +		case OF_DT_END_NODE:
>> +			dtp++;
>> +			break;
>> +		case OF_DT_BEGIN_NODE:
>> +			len = strlen((char *)(++dtp));
>> +			dtp += 1 + len / 4;
>> +			break;
>> +		case OF_DT_PROP:
>> +			len = dtp[1];
>> +			dtp += 3 + (len + 3) / 4;
>> +			break;
>> +		case OF_DT_END:
>> +			fatal("Not enough nops -- need %d more\n", count);
>> +			return;
>> +		default:
>> +			fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp)
>> +		}
>> +}
>> +#endif
>> +
>> +/**
>> + * conv_flattree_inplace upgrade the version of a boot_param_header
>> + * @tree: pointer to the device tree header to convert
>> + *
>> + * Converts a v1, 2, 3 device tree (of at least MIN_VERSION)
>> + * in place to OUT_VERSION (16) format, usable by flatdevtree.c
>> + */
>> +void conv_flattree_inplace(struct boot_param_header *tree)
>> +{
>> +	u32 *dtp;
>> +	u32 need = 0, nops;
>> +	int slen;
>> +
>> +	if (tree->magic != OF_DT_HEADER)
>> +		fatal("%s: no magic", __FUNCTION__);
>
> More pointless tests...

It says you didn't pass a tree ... yea, its dumb, but I prefer an 
explicit error to figuring out where a machine check came from.

>
>> +	if (tree->last_comp_version > 3)
>> +		return;			/* don't know what to do */
>
> Rather, don't need to do anything.

If the tree is >= 16 then we don't presently need to do anything.   If 
there is a theoritical v4 tree we don't know what to do.  And if output 
version is 17 but input is 16 we don't know what to do either, because 
there likely aren't nops in the tree to consume.  I suppose we could 
preceed it with a check for version == OUTPUT_VERSION, but then I'm 
sure I'd get pointless differentation :-).

>
>> +
>> +	if (tree->version < MIN_VERSION) {
>> +		printf("%s: Warning: can't handle version %d tree\n",
>> +				__FUNCTION__, tree->version);
>> +		return;
>> +	}
>> +
>> +	if (tree->version < 2)
>> +		need++;		/* boot_cpu_id */
>> +
>> +	if (tree->version < 3)
>> +		need++;		/* dt_string_size */
>> +
>> +	if (OUT_VERSION > 16)
>> +		need++;		/* dt_struct_size */
>> +
>> +	dtp = (void *)tree + tree->off_dt_struct;
>> +
>> +	slen = check_v123_tree(dtp, (void *)tree + tree->totalsize);
>> +	if (slen < 0)
>> +		fatal("device tree check failed\n");
>> +
>> +	nops = nop_to_v16(dtp);
>> +
>> +	if (need & 1)		/* keep 8 byte alignment of mem reserve */
>> +		need++;
>> +
>> +	if (need > nops)
>> +		fatal("Didn't find enough space to add new header fields\n\r"
>> +			"(needed %d found %d tree %p)", need, nops, tree);
>> +
>> +	/* ok now compress the dtb struct */
>> +	move_nops_fwd(dtp, need);
>> +	dtp += need;
>> +
>> +	/*
>> +	 * move mem_rsvmap and dt_strings if they are before dt_struct
>> +	 * onto our nops .  Adjust start addresses for the 3 sections.
>> +	 */
>
> Hrm.  Do we really need to worry about this case.  You may be
> producing v2 trees in kexec-tools, but do they actually have the
> blocks out of order?  dtc certainly never produced them that way.

Out of order?  There has never been a spec as to the order of the 
blocks, only the implicit assumption that they follow the device tree 
header in a reasonably packed sequence.  booting-without-of says it 
must be in ram,; the offsets are unsigned 32 bit quantities.

As to the order, used, the first implemntation was the kernel which 
writes memreserve, strings, then struct (both the openfirmware client 
in prom_init and the iSeries procedural library in dt.c).  The second 
implentation written is a procedural based library (similar to iseries, 
never published, but still used internally) that starts with a 
pre-built header and string table, builds the dt_struct as the 
functions are called, and when finished copies the memreserve table and 
fills in the dt_size, total size, and memreserve offset.

fs2dt writes memreserve, struct, then strings.  Aparently the same as 
dtc.  But yes, the strings can be before the struct, and the mem 
reserve may or may not be when the strings are before the struct.

>
>> +	if ((tree->off_mem_rsvmap < tree->off_dt_struct) ||
>> +		(tree->off_dt_strings < tree->off_dt_struct)) {
>> +		int start, end;
>> +		void *ptr;
>> +
>> +		if (tree->off_mem_rsvmap < tree->off_dt_strings)
>> +			start = tree->off_mem_rsvmap;
>> +		else
>> +			start = tree->off_dt_strings;
>> +
>> +		end = tree->off_dt_struct;
>> +		ptr = (void *)tree + start;
>> +
>> +		memmove(ptr + 4 * need, ptr, end - start);
>> +
>> +		if (tree->off_mem_rsvmap < tree->off_dt_struct)
>> +			tree->off_mem_rsvmap += 4 * need;
>> +		if (tree->off_dt_strings < tree->off_dt_struct)
>> +			tree->off_dt_strings += 4 * need;
>> +	}
>> +	tree->off_dt_struct += 4 * need;
>> +
>> +	/* ok now we have space to extend the header. */
>> +	if (tree->version < 2 && MIN_VERSION < 2) {
>> +		tree->boot_cpuid_phys = 0;	/* default, caller can fix */
>> +	}
>> +
>> +	/* calculate size of dt_strings_size */
>> +	if (tree->version < 3 && MIN_VERSION < 3) {
>> +		int end = tree->totalsize;
>> +
>> +		if (tree->off_dt_strings < tree->off_mem_rsvmap)
>> +			end = tree->off_mem_rsvmap;
>> +
>> +		if ((tree->off_dt_strings < tree->off_dt_struct) &&
>> +				(end > tree->off_dt_struct))
>> +			end = tree->off_dt_struct;
>> +
>> +		tree->dt_strings_size = end - tree->off_dt_strings;
>> +	}
>> +
>> +#if OUT_VERSION > 16
>> +	tree->dt_struct_size = 4 * slen;
>> +#endif
>> +
>> +	tree->version = OUT_VERSION;
>> +	tree->last_comp_version = OUT_COMPAT;
>> +
>> +	return;
>> +}
>> Index: kernel/arch/powerpc/boot/Makefile
>> ===================================================================
>> --- kernel.orig/arch/powerpc/boot/Makefile	2007-09-20 
>> 17:42:24.000000000 -0500
>> +++ kernel/arch/powerpc/boot/Makefile	2007-09-20 17:49:04.000000000 
>> -0500
>> @@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
>>  	$(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix 
>> $(obj)/,$(zlibheader))
>>
>>  src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c 
>> flatdevtree_misc.c \
>> -		marshal.c memranges.c kexec.c \
>> +		flatdevtree_conv.c marshal.c memranges.c kexec.c \
>>  		ns16550.c serial.c simple_alloc.c div64.S util.S \
>>  		gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
>>  		4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
>> Index: kernel/arch/powerpc/boot/ops.h
>> ===================================================================
>> --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-20 17:42:24.000000000 
>> -0500
>> +++ kernel/arch/powerpc/boot/ops.h	2007-09-20 17:49:04.000000000 -0500
>> @@ -81,7 +81,10 @@ struct loader_info {
>>  };
>>  extern struct loader_info loader_info;
>>
>> +struct boot_param_header;
>> +
>>  void start(void);
>> +void conv_flattree_inplace(struct boot_param_header *tree);
>>  int ft_init(void *dt_blob, unsigned int max_size, unsigned int 
>> max_find_device);
>>  int serial_console_init(void);
>>  int ns16550_console_init(void *devp, struct serial_console_data 
>> *scdp);
>> Index: kernel/arch/powerpc/boot/kexec.c
>> ===================================================================
>> --- kernel.orig/arch/powerpc/boot/kexec.c	2007-09-20 
>> 17:42:24.000000000 -0500
>> +++ kernel/arch/powerpc/boot/kexec.c	2007-09-20 17:49:04.000000000 
>> -0500
>> @@ -99,6 +99,7 @@ void kexec_platform_init(struct boot_par
>>  	move_slaves_up();
>>
>>  	setup_initial_heap();
>> +	conv_flattree_inplace(dt_blob);
>>  	init_flat_tree(dt_blob);
>>  	/*
>>  	 * drivers can malloc and read the tree, but not realloc later
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>>
>
> -- 
> David Gibson			| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ 
> _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson
>

^ permalink raw reply

* Re: [PATCH 1/2] qemu platform, v2
From: Christoph Hellwig @ 2007-09-24  7:46 UTC (permalink / raw)
  To: Christoph Hellwig, Milton Miller, linuxppc-dev, Paul Mackerras,
	Rob Landley
In-Reply-To: <20070924040047.GK8058@localhost.localdomain>

On Mon, Sep 24, 2007 at 02:00:47PM +1000, David Gibson wrote:
> Basically because PReP support doesn't work under arch/powerpc.
> Getting it working properly is something that should happen, but will
> take a while.  In the meantime, getting something that's sufficient to
> get working under just qemu's version of prep, without using the
> abominable openhackware is a quicker path to a usable arch/powerpc
> kernel under qemu.

Sounds fair.  Care to add something like this to the Kconfig help
text?

^ permalink raw reply

* Re: [patch 6/6] Walnut zImage wrapper
From: Wolfgang Grandegger @ 2007-09-24  7:49 UTC (permalink / raw)
  To: Josh Boyer; +Cc: linuxppc-dev, David Gibson
In-Reply-To: <20070905113604.746ee01c@weaponx.rchland.ibm.com>

Josh Boyer wrote:
> Updated patch below
> 
> Add zImage wrapper for walnut board
> 
> Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
> 
> ---
>  arch/powerpc/boot/Makefile          |    3 
>  arch/powerpc/boot/dcr.h             |    5 +
>  arch/powerpc/boot/treeboot-walnut.c |  131 ++++++++++++++++++++++++++++++++++++
>  3 files changed, 138 insertions(+), 1 deletion(-)
> 
> --- linux-2.6.orig/arch/powerpc/boot/Makefile
> +++ linux-2.6/arch/powerpc/boot/Makefile
> @@ -49,7 +49,7 @@ src-wlib := string.S crt0.S stdio.c main
>  src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
>  		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
>  		ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
> -		cuboot-pq2.c cuboot-bamboo.c
> +		cuboot-pq2.c cuboot-bamboo.c treeboot-walnut.c
[deletions]

The addition of treeboot-walnut.c breaks compilation of Linux-2.6 for 
the lite5200 using the ppc_6xx toolchain of the ELDK 4.1:

   MODPOST vmlinux.o
WARNING: vmlinux.o(.text+0x14): Section mismatch: reference to 
.init.text:prom_init (between '__start' and '__after_mmu_off')
WARNING: vmlinux.o(.text+0x28): Section mismatch: reference to 
.init.text:early_init (between '__start' and '__after_mmu_off')
WARNING: vmlinux.o(.text+0x340c): Section mismatch: reference to 
.init.text:machine_init (between 'start_here' and 'set_context')
WARNING: vmlinux.o(.text+0x3414): Section mismatch: reference to 
.init.text:MMU_init (between 'start_here' and 'set_context')
WARNING: vmlinux.o(.text+0x343e): Section mismatch: reference to 
.init.text:start_kernel (between 'start_here' and 'set_context')
WARNING: vmlinux.o(.text+0x3442): Section mismatch: reference to 
.init.text:start_kernel (between 'start_here' and 'set_context')
   GEN     .version
   CHK     include/linux/compile.h
   UPD     include/linux/compile.h
   CC      init/version.o
   LD      init/built-in.o
   LD      vmlinux
   SYSMAP  System.map
   BOOTAS  arch/powerpc/boot/string.o
   BOOTAS  arch/powerpc/boot/crt0.o
   BOOTCC  arch/powerpc/boot/stdio.o
   BOOTCC  arch/powerpc/boot/main.o
   BOOTCC  arch/powerpc/boot/flatdevtree.o
   BOOTCC  arch/powerpc/boot/flatdevtree_misc.o
   BOOTCC  arch/powerpc/boot/ns16550.o
   BOOTCC  arch/powerpc/boot/serial.o
   BOOTCC  arch/powerpc/boot/simple_alloc.o
   BOOTAS  arch/powerpc/boot/div64.o
   BOOTAS  arch/powerpc/boot/util.o
   BOOTCC  arch/powerpc/boot/gunzip_util.o
   BOOTCC  arch/powerpc/boot/elf_util.o
   BOOTCC  arch/powerpc/boot/inffast.o
   BOOTCC  arch/powerpc/boot/inflate.o
   BOOTCC  arch/powerpc/boot/inftrees.o
   BOOTCC  arch/powerpc/boot/devtree.o
   BOOTCC  arch/powerpc/boot/oflib.o
   BOOTCC  arch/powerpc/boot/ofconsole.o
   BOOTCC  arch/powerpc/boot/4xx.o
   BOOTCC  arch/powerpc/boot/ebony.o
   BOOTCC  arch/powerpc/boot/mv64x60.o
   BOOTCC  arch/powerpc/boot/mpsc.o
   BOOTCC  arch/powerpc/boot/mv64x60_i2c.o
   BOOTCC  arch/powerpc/boot/cuboot.o
   BOOTCC  arch/powerpc/boot/bamboo.o
   BOOTAR  arch/powerpc/boot/wrapper.a
   BOOTCC  arch/powerpc/boot/of.o
   BOOTCC  arch/powerpc/boot/cuboot-83xx.o
   BOOTCC  arch/powerpc/boot/cuboot-85xx.o
   BOOTCC  arch/powerpc/boot/holly.o
   BOOTCC  arch/powerpc/boot/cuboot-ebony.o
   BOOTCC  arch/powerpc/boot/treeboot-ebony.o
   BOOTCC  arch/powerpc/boot/prpmc2800.o
   BOOTAS  arch/powerpc/boot/ps3-head.o
   BOOTAS  arch/powerpc/boot/ps3-hvcall.o
   BOOTCC  arch/powerpc/boot/ps3.o
   BOOTCC  arch/powerpc/boot/treeboot-bamboo.o
   BOOTCC  arch/powerpc/boot/cuboot-sequoia.o
   BOOTCC  arch/powerpc/boot/treeboot-walnut.o
{standard input}: Assembler messages:
{standard input}:184: Error: Unrecognized opcode: `mfdcr'
{standard input}:185: Error: Unrecognized opcode: `mfdcr'
{standard input}:186: Error: Unrecognized opcode: `mfdcr'
{standard input}:217: Error: Unrecognized opcode: `mtdcr'
make[1]: *** [arch/powerpc/boot/treeboot-walnut.o] Error 1
make: *** [uImage] Error 2

It looks like the ppc_6xx toolchain does not know the opcode above. I 
wonder why files for other PowerPC sub-archs like 4xx are compiled with 
the wrong compiler. Have I missed something?

And the WARNING above on "Section mismatch" looks strange as well (still 
present in 2.6.23-rc7).

Thanks for help.

Wolfgang.

^ permalink raw reply

* Re: [PATCH 1/15] boot: find initrd location from device-tree
From: Milton Miller @ 2007-09-24  8:02 UTC (permalink / raw)
  To: David Gibson; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <20070924025824.GD8058@localhost.localdomain>


On Sep 23, 2007, at 9:58 PM, David Gibson wrote:

> On Fri, Sep 21, 2007 at 06:03:24PM -0500, Milton Miller wrote:
>> Some platforms have a boot agent that can create or modify properties 
>> in
>> the device-tree and load images into memory.  Provide a helper to set
>> loader_info used by prep_initrd().
>>
>> Signed-off-by: Milton Miller <miltonm@bga.com>
>> Acked-by: David Gibson <david@gibson.dropbear.id.au>
>
> Hrm, despite my earlier ack, I'm going to whinge about a few nits
> here.
>
>> ---
>> re 12168
>> rediffed types.h, offset in ops.h
>>
>> Index: kernel/arch/powerpc/boot/ops.h
>> ===================================================================
>> --- kernel.orig/arch/powerpc/boot/ops.h	2007-09-17 22:12:47.000000000 
>> -0500
>> +++ kernel/arch/powerpc/boot/ops.h	2007-09-17 22:12:51.000000000 -0500
>> @@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3
>>  void __dt_fixup_mac_addresses(u32 startindex, ...);
>>  #define dt_fixup_mac_addresses(...) \
>>  	__dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
>> +void dt_find_initrd(void);
>>
>>
>>  static inline void *find_node_by_linuxphandle(const u32 linuxphandle)
>> Index: kernel/arch/powerpc/boot/types.h
>> ===================================================================
>> --- kernel.orig/arch/powerpc/boot/types.h	2007-09-17 
>> 22:12:47.000000000 -0500
>> +++ kernel/arch/powerpc/boot/types.h	2007-09-17 22:12:51.000000000 
>> -0500
>> @@ -12,6 +12,8 @@ typedef short			s16;
>>  typedef int			s32;
>>  typedef long long		s64;
>>
>> +#define UINT_MAX	0xFFFFFFFF
>
> I actually don't like this constant - at the point you compare you
> care, explicitly, about the value not being over 32-bits, rather than
> whether it fits a uint, so the named constant is more misleading than
> helpful.

Arguable, I don't like counting F's or zeros in C code.

It is used as the max address that the wrapper deals with, both here 
and memranges, which happens to be 32 bits.

Actually it cares about overflowing the unsigned long in loader_info, 
not that the address fits in 32 bits.

So it should be ULONG_MAX now (malloc and all the address code was 
changed to use unsigned long instead of unsigned int since the patch 
was written).

And dt_xlate needs the same information.  Its is using a hardcoded 64 
bit constant to provide the a simiar check.


>> +
>>  #define min(x,y) ({ \
>>  	typeof(x) _x = (x);	\
>>  	typeof(y) _y = (y);	\
>> Index: kernel/arch/powerpc/boot/devtree.c
>> ===================================================================
>> --- kernel.orig/arch/powerpc/boot/devtree.c	2007-09-17 
>> 22:12:47.000000000 -0500
>> +++ kernel/arch/powerpc/boot/devtree.c	2007-09-17 22:12:51.000000000 
>> -0500
>> @@ -1,6 +1,7 @@
>>  /*
>>   * devtree.c - convenience functions for device tree manipulation
>>   * Copyright 2007 David Gibson, IBM Corporation.
>> + * Copyright 2007 Milton Miller, IBM Corporation.
>>   * Copyright (c) 2007 Freescale Semiconductor, Inc.
>>   *
>>   * Authors: David Gibson <david@gibson.dropbear.id.au>
>> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const c
>>
>>  	return 0;
>>  }
>> +
>> +/**
>> + * dt_find_initrd - set loader initrd location based on existing 
>> properties
>> + *
>> + * finds the linux,initrd-start and linux,initrd-end properties in
>> + * the /chosen node and sets the loader initrd fields accordingly.
>> + *
>> + * Use this if your loader sets the properties to allow other code to
>> + * relocate the tree and/or cause r3 and r4 to be set on true OF
>> + * platforms.
>
> I am unable to make sense of the paragraph above.

The phrase "relocate the tree" should be "relocate the initrd", which 
the wrapper will do if it located below vmlinux.size.  Also, r3 and r4 
need to be set when booting the kernel from a client interface with an 
initrd so it can take it into consideration when choosing the location 
to build the flat tree.

How about:

Filling in the loader info allows main.c to be aware of the initrd, 
meaning prep_initrd will move the initrd if it will be overwritten when 
the kernel is copied to its runtime location.  In addition, if you are 
booting the kernel from a client interface instead of a flat device 
tree, this also causes r3 and r4 to be set so the kernel can avoid 
overwriting the initrd when creating the flat tree.

>
>> + */
>> +void dt_find_initrd(void)
>> +{
>> +	int rc;
>> +	unsigned long long initrd_start, initrd_end;
>> +	void *devp;
>> +	static const char start_prop[] = "linux,initrd-start";
>> +	static const char end_prop[] = "linux,initrd-end";
>
> I think these constants are more obscuring than useful.

They are useful to the extent they reduce the number of source 
characters causing about 8 less line wraps.  Since they are used 
multiple places, the compiler only needs to emit one copy of this byte 
sequence.  Admitedly you made this point in a prior review.

>
>> +
>> +	devp = finddevice("/chosen");
>> +	if (! devp) {
>> +		return;
>> +	}
>
> CodingStyle would not put { } here.

Yea, nit.  not sure why I have the braces there, I usually follow that 
one.  And what's that space doing after !?

>
>> +
>> +	rc = getprop(devp, start_prop, &initrd_start, sizeof(initrd_start));
>> +	if (rc < 0)
>> +		return;				/* not found */
>> +	/* The properties had to be 8 bytes until 2.6.22 */
>> +	if (rc == sizeof(unsigned long)) {
>> +		unsigned long tmp;
>> +		memcpy(&tmp, &initrd_start, rc);
>> +		initrd_start = tmp;
>> +	} else if (rc != sizeof(initrd_start)) {	/* now they
>> can be 4 */
>
> Right.  8 bytes and 4 bytes, so you should be using explicit length
> types instead of long and long long.

Ok, I guess we ahve u32 and u64 in types.h now.  But there is other 
code in the wrapper that assumes its compiled 32 bit ILP.

>
>> +		printf("unexpected length of %s in /chosen!\n\r", start_prop);
>> +		return;
>
> All these printf() / return stanzas add a lot of verbosity to this
> function.  Any way they can be consolidated a bit, maybe a single
> error path that just prints the property values, so the user can
> figure out what was wrong with them.

On a prior review I got asked to split the reasons for ingoring the 
values below (the > 32 bit address from end < start cases).  Admitedly 
without all the detailed errors the justification for the string 
varables is reduced.

>
>> +	}
>> +
>> +	rc = getprop(devp, end_prop, &initrd_end, sizeof(initrd_end));
>> +	if (rc < 0) {
>> +		printf("chosen has %s but no %s!\n\r", start_prop, end_prop);
>> +		return;
>> +	}
>> +	if (rc == sizeof(unsigned long)) {
>> +		unsigned long tmp;
>> +		memcpy(&tmp, &initrd_end, rc);
>> +		initrd_end = tmp;
>> +	} else if (rc != sizeof(initrd_end)) {
>> +		printf("unexpected length of %s in /chosen!\n\r", end_prop);
>> +		return;
>> +	}
>> +
>> +	/* Check for presence, ignore if (partially) loaded above 32 bits */
>> +	if (initrd_start == initrd_end) {
>> +		printf("ignoring empty device-tree supplied initrd\n");
>> +	} else if (initrd_start > initrd_end) {
>> +		printf("ignoring device-tree supplied initrd: start 0x%llx"
>> +				" > end 0x%llx \n", initrd_start, initrd_end);
>> +	} else if (initrd_end > UINT_MAX) {
>> +		printf("ignoring device-tree supplied initrd:"
>> +				" end 0x%llx > 32 bits\n", initrd_end);
>> +	} else {
>> +		loader_info.initrd_addr = initrd_start;
>> +		loader_info.initrd_size  = initrd_end - initrd_start;
>> +	}
>> +}
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>>
>
> -- 
> David Gibson			| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ 
> _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson
>

^ permalink raw reply

* [PATCH] fix mace_handle_misc_intrs compilation
From: Olaf Hering @ 2007-09-24  8:15 UTC (permalink / raw)
  To: Andrew Morton, linuxppc-dev, netdev


Fix compilation after incomplete struct net_device changes.

Signed-off-by: Olaf Hering <olaf@aepfle.de>

---
 drivers/net/mace.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

--- a/drivers/net/mace.c
+++ b/drivers/net/mace.c
@@ -633,7 +633,7 @@ static void mace_set_multicast(struct ne
     spin_unlock_irqrestore(&mp->lock, flags);
 }
 
-static void mace_handle_misc_intrs(struct mace_data *mp, int intr)
+static void mace_handle_misc_intrs(struct mace_data *mp, int intr, struct net_device *dev)
 {
     volatile struct mace __iomem *mb = mp->mace;
     static int mace_babbles, mace_jabbers;
@@ -669,7 +669,7 @@ static irqreturn_t mace_interrupt(int ir
     spin_lock_irqsave(&mp->lock, flags);
     intr = in_8(&mb->ir);		/* read interrupt register */
     in_8(&mb->xmtrc);			/* get retries */
-    mace_handle_misc_intrs(mp, intr);
+    mace_handle_misc_intrs(mp, intr, dev);
 
     i = mp->tx_empty;
     while (in_8(&mb->pr) & XMTSV) {
@@ -682,7 +682,7 @@ static irqreturn_t mace_interrupt(int ir
 	 */
 	intr = in_8(&mb->ir);
 	if (intr != 0)
-	    mace_handle_misc_intrs(mp, intr);
+	    mace_handle_misc_intrs(mp, intr, dev);
 	if (mp->tx_bad_runt) {
 	    fs = in_8(&mb->xmtfs);
 	    mp->tx_bad_runt = 0;
@@ -817,7 +817,7 @@ static void mace_tx_timeout(unsigned lon
 	goto out;
 
     /* update various counters */
-    mace_handle_misc_intrs(mp, in_8(&mb->ir));
+    mace_handle_misc_intrs(mp, in_8(&mb->ir), dev);
 
     cp = mp->tx_cmds + NCMDS_TX * mp->tx_empty;
 

^ permalink raw reply

* Re: [PATCH] fix mace_handle_misc_intrs compilation
From: Andrew Morton @ 2007-09-24  8:22 UTC (permalink / raw)
  To: Olaf Hering; +Cc: linuxppc-dev, netdev
In-Reply-To: <20070924081501.GA1797@aepfle.de>

On Mon, 24 Sep 2007 10:15:01 +0200 Olaf Hering <olaf@aepfle.de> wrote:

> Fix compilation after incomplete struct net_device changes.

yup, thanks, Kamalesh Babulal has already sent in an identical
patch.

^ permalink raw reply

* Re: [PATCH 5/15] bootwrapper: occuppied memory ranges
From: Milton Miller @ 2007-09-24  9:33 UTC (permalink / raw)
  To: David Gibson; +Cc: ppcdev, Paul Mackerras
In-Reply-To: <20070924030937.GF8058@localhost.localdomain>

On Sep 23, 2007, at 10:09 PM, David Gibson wrote:
> On Fri, Sep 21, 2007 at 06:04:18PM -0500, Milton Miller wrote:
>> Add a set of library routines to manage gross memory allocations.
>>
>> This code uses an array in bss to store upto 32 entrys with merging
>> representing a range of memory below rma_end (aka end of real mode
>> memory at 0).
>>
>> To use this code, a platform would set rma_end (find_rma_end), mark
>> memory ranges occupied (add_known_ranges et al), initialize malloc in
>> the spaces between (ranges_init_malloc), and optionally use the 
>> supplied
>> vmlinux_alloc may be used.
>
> Urg.  It's an awful lot of code for the bootwrapper.  Am I right in
> understanding that the only reason to use the ranges code is for the
> ranges based malloc() and vmlinux_alloc() you get out of it?

Yes.

The ranges based malloc is simple_alloc after finding a sutable chunk 
to operate in.

When doing a kexec, there are several chunks of memory to avoid.  There 
are at least the wrapper, the initrd, the input device tree, and 
possibly rtas and tce tables.  The last two are avoided by parsing the 
memory resrve list in the flat tree blob.

In practice, on 64 bit powerpc kexec-tools loads the kernel (in this 
case zImage) immediately following the old kernel _end (becauset the 
kernel doesnt' allow otherwise, like 32 bit and most other platforms 
do).  If the kernel being execd is larger than the kernel invoking 
kexec, then the vmlinux will not fit below the wrapper, but when they 
are the same it will fit.  So in the malloc region we need space for 
random temps, the final device tree, the kernel, and possibly the 
initrd -- especially if its attached to the zImage instead of supplied 
by kexec-tools.

While I titled this platform kexec, in reality, it is a generic chain 
looading platform for flat device trees in that it is invoked with the 
same calling conveintions as it calls the kernel.  With the current 
policy of run-where-loadeed, the wrapper has to be able to find out 
what memory is available.  It may be above or below itself, and the 
bulk of available memory may be after any of the above mentioned 
ranges.  The only information is the the flat device tree and its 
knowledge of itself.  Most of this code deals with building the sorted 
list of what memory is used.

Actually, there is a hole in that malloc may be initialzed below the 
vmlinux.size and the initrd and deviece tree could end up overwritten.  
This can't be eliminated without doing something like prpmc2800 where 
the kernel decompression is started and the elf header is read before 
initializing malloc.  In practice has not  triggered because the 
vmlinux will be malloced before the device tree without an initrd, and 
with it the kernel is likely smaller than the wrapper (since the memory 
chunk at 0 is avoided, it requires the end of some other chunk to be 
low in memory).

At one point you had mentioned considering changes to run out of bss 
and handling the initrd and kernel with calls to memmove; any such 
movement would requrie similar information to what is being built into 
the storted structure in this code to support externally loaded initrds 
and device-trees, which could not be allocated into the bss wihout 
arbitrarilly limiting their size.

I've made several changes to the split btween memranges.c and kexec.c 
over time.  Perhaps there are more left.  There is a bit of policy in 
the ranges malloc initialilzation; that could probably be eliminated by 
query functions for the largest chunk. The vmlinux alloc could try just 
0 and malloc().  And the area from the last occupied range to roa_end 
should be available for malloc as well as the kernel.

milton

^ permalink raw reply

* Re: AMCC yosemite 440ep PCI slot doesn't work.
From: Andrew Liu @ 2007-09-24  9:34 UTC (permalink / raw)
  To: Valentine Barshak; +Cc: linuxppc-dev
In-Reply-To: <46F3DFCA.1040700@ru.mvista.com>

By default, it is IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE
 
 I change it to IRQ_SENSE_EDGE | IRQ_POLARITY_NEGATIVE  or
IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE.
It  displays:
eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
eth2: no IPv6 routers present
NETDEV WATCHDOG: eth2: transmit timed out
eth2: Transmit timeout, status 0c 0005 c07f media 10.
eth2: Tx queue start entry 4  dirty entry 0.
eth2:  Tx descriptor 0 is 0008a05a. (queue head)
eth2:  Tx descriptor 1 is 0008a04e.
eth2:  Tx descriptor 2 is 0008a046.
eth2:  Tx descriptor 3 is 0008a05a.
eth2: link up, 100Mbps, full-duplex, lpa 0x45E1

and
root@localhost:/root> ifconfig  eth2
eth2      Link encap:Ethernet  HWaddr 00:0E:2E:7E:F5:E6 
          inet addr:128.224.149.13  Bcast:128.224.255.255  Mask:255.255.0.0
          inet6 addr: fe80::20e:2eff:fe7e:f5e6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)
          Interrupt:25 Base address:0x6f00


and
root@localhost:/root> cat /proc/interrupts
           CPU0      
  2:          0  UIC0 Edge      IBM IIC
  7:          0  UIC0 Edge      IBM IIC
 10:      11961  UIC0 Edge      MAL TX EOB
 11:      18471  UIC0 Edge      MAL RX EOB
 25:          0  UIC0 Edge      eth2
 32:          0  UIC1 Edge      MAL SERR
 33:          0  UIC1 Edge      MAL TX DE
 34:          0  UIC1 Edge      MAL RX DE
 40:         32  UIC1 Edge      ohci_hcd:usb1
 60:          0  UIC1 Edge      EMAC
BAD:          0


Can PCI slot use level trigger?

give me some advice.

Thanks.

Valentine Barshak wrote:
> Andrew Liu wrote:
>> Hello All,
>>
>> when insert a  RealTek RTL8139 network card into PCI slot,
>> After system boot up,
>>
>> root@localhost:/root> ifconfig eth2 192.168.17.12
>> irq 25: nobody cared (try booting with the "irqpoll" option)
>> Call Trace:
>> [cf135af0] [c0008820] show_stack+0x48/0x190 (unreliable)
>> [cf135b20] [c003c414] __report_bad_irq+0x34/0xac
>> [cf135b40] [c003c714] note_interrupt+0x288/0x2c8
>> [cf135b70] [c003b818] __do_IRQ+0x104/0x110
>> [cf135b90] [c0006900] do_IRQ+0xbc/0xc0
>> [cf135ba0] [c00020c0] ret_from_except+0x0/0x18
>> [cf135c60] [00000019] 0x19
>> [cf135c90] [c000668c] do_softirq+0x54/0x58
>> [cf135ca0] [c001df40] irq_exit+0x48/0x58
>> [cf135cb0] [c00068b4] do_IRQ+0x70/0xc0
>> [cf135cc0] [c00020c0] ret_from_except+0x0/0x18
>> [cf135d80] [c003c2b4] setup_irq+0x1ac/0x200
>> [cf135da0] [c003c3cc] request_irq+0xc4/0xd8
>> [cf135dd0] [c0122328] rtl8139_open+0x38/0x210
>> [cf135df0] [c0187500] dev_open+0x7c/0xcc
>> [cf135e10] [c0187420] dev_change_flags+0x16c/0x1d0
>> [cf135e30] [c01cbff0] devinet_ioctl+0x604/0x720
>> [cf135ea0] [c01cc1f8] inet_ioctl+0x98/0xbc
>> [cf135eb0] [c0179328] sock_ioctl+0x60/0x260
>> [cf135ed0] [c006c360] do_ioctl+0x38/0x84
>> [cf135ee0] [c006c438] vfs_ioctl+0x8c/0x40c
>> [cf135f10] [c006c7f8] sys_ioctl+0x40/0x74
>> [cf135f40] [c0001a84] ret_from_syscall+0x0/0x3c
>> handlers:
>> [<c0122bd4>] (rtl8139_interrupt+0x0/0x52c)
>> Disabling IRQ #25
>> root@localhost:/root>
>> Message from syslogd@localhost at Thu Jan  1 00:02:13 1970 ...
>> localhost kernel: Disabling IRQ #25
>>
>> root@localhost:/root>
>>
>>
>>  The system boot up information as follows:
>> root@localhost:/root> dmesg
>> Linux version 2.6.23-rc6-gea60adb5 (sliu@localhost.localdomain) (gcc
>> version 4.0.0 (DENX ELDK 4.1 4.0.0)) #3 Fri Sep 21 18:37:59 CST 2007
>> AMCC PowerPC 440EP Yosemite Platform
>> Entering add_active_range(0, 0, 65536) 0 entries of 256 used
>> Zone PFN ranges:
>>   DMA             0 ->    65536
>>   Normal      65536 ->    65536
>> Movable zone start PFN for each node
>> early_node_map[1] active PFN ranges
>>     0:        0 ->    65536
>> On node 0 totalpages: 65536
>>   DMA zone: 512 pages used for memmap
>>   DMA zone: 0 pages reserved
>>   DMA zone: 65024 pages, LIFO batch:15
>>   Normal zone: 0 pages used for memmap
>>   Movable zone: 0 pages used for memmap
>> Built 1 zonelists in Zone order.  Total pages: 65024
>> Kernel command line: root=/dev/nfs rw
>> nfsroot=128.224.149.6:/tftpboot/sliu/rootfs
>> ip=128.224.149.11::128.224.149.1:255.255.255.0:yosemite:eth0:off
>> console=ttyS0,9600
>> PID hash table entries: 1024 (order: 10, 4096 bytes)
>> console [ttyS0] enabled
>> Dentry cache hash table entries: 32768 (order: 5, 131072 bytes)
>> Inode-cache hash table entries: 16384 (order: 4, 65536 bytes)
>> Memory: 256896k available (2052k kernel code, 716k data, 152k init, 0k
>> highmem)
>> Calibrating delay loop... 798.72 BogoMIPS (lpj=1597440)
>> Mount-cache hash table entries: 512
>> NET: Registered protocol family 16
>> PCI: Probing PCI hardware
>> PCI: Scanning bus 0000:00
>> PCI: Found 0000:00:0c.0 [10ec/8139] 000200 00
>> PCI: Calling quirk c000444c for 0000:00:0c.0
>> PCI: Fixups for bus 0000:00
>> PCI: Bus scan for 0000:00 returning with max=00
>> PCI: fixup irq: (0000:00:0c.0) got 25
>> SCSI subsystem initialized
>> usbcore: registered new interface driver usbfs
>> usbcore: registered new interface driver hub
>> usbcore: registered new device driver usb
>> NET: Registered protocol family 2
>> IP route cache hash table entries: 2048 (order: 1, 8192 bytes)
>> TCP established hash table entries: 8192 (order: 4, 65536 bytes)
>> TCP bind hash table entries: 8192 (order: 3, 32768 bytes)
>> TCP: Hash tables configured (established 8192 bind 8192)
>> TCP reno registered
>> io scheduler noop registered
>> io scheduler anticipatory registered (default)
>> io scheduler deadline registered
>> io scheduler cfq registered
>> PCI: Calling quirk c00fbab4 for 0000:00:0c.0
>> PCI: Calling quirk c02ae3b8 for 0000:00:0c.0
>> Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled
>> serial8250: ttyS0 at MMIO 0x0 (irq = 0) is a 16550A
>> serial8250: ttyS1 at MMIO 0x0 (irq = 1) is a 16550A
>> RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
>> PPC 4xx OCP EMAC driver, version 3.54
>> mal0: initialized, 4 TX channels, 2 RX channels
>> zmii0: bridge in RMII mode
>> eth0: emac0, MAC 00:10:ec:00:87:42
>> eth0: found Generic MII PHY (0x01)
>> eth1: emac1, MAC 00:00:00:00:00:00
>> eth1: found Generic MII PHY (0x03)
>> 8139too Fast Ethernet driver 0.9.28
>> eth2: RealTek RTL8139 at 0xd1012f00, 00:0e:2e:7e:f5:e6, IRQ 25
>> eth2:  Identified 8139 chip type 'RTL-8100B/8139D'
>> pegasus: v0.6.14 (2006/09/27), Pegasus/Pegasus II USB Ethernet driver
>> usbcore: registered new interface driver pegasus
>> Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2
>> ide: Assuming 33MHz system bus speed for PIO modes; override with
>> idebus=xx
>> usbmon: debugfs is not available
>> ohci_hcd: 2006 August 04 USB 1.1 'Open' Host Controller (OHCI) Driver
>> ppc-soc-ohci ppc-soc-ohci.0: USB Host Controller
>> ppc-soc-ohci ppc-soc-ohci.0: new USB bus registered, assigned bus
>> number 1
>> ppc-soc-ohci ppc-soc-ohci.0: irq 40, io mem 0xef601000
>> usb usb1: configuration #1 chosen from 1 choice
>> hub 1-0:1.0: USB hub found
>> hub 1-0:1.0: 2 ports detected
>> Initializing USB Mass Storage driver...
>> usbcore: registered new interface driver usb-storage
>> USB Mass Storage support registered.
>> ether gadget: using random self ethernet address
>> ether gadget: using random host ethernet address
>> usb0: Ethernet Gadget, version: May Day 2005
>> usb0: using musbhsfc_udc, OUT ep2 IN ep1 STATUS ep3
>> usb0: MAC 66:91:74:ab:fb:61
>> usb0: HOST MAC 1a:b5:87:5d:8f:00
>> usb0: RNDIS ready
>> musbhsfc_udc: registered gadget driver 'ether'
>> TCP cubic registered
>> NET: Registered protocol family 1
>> NET: Registered protocol family 17
>> usb 1-1: new full speed USB device using ppc-soc-ohci and address 2
>> usb 1-1: configuration #1 chosen from 1 choice
>> eth0: link is up, 100 FDX, pause enabled
>> scsi0 : SCSI emulation for USB Mass Storage devices
>> usb-storage: device found at 2
>> usb-storage: waiting for device to settle before scanning
>> IP-Config: Complete:
>>       device=eth0, addr=128.224.149.11, mask=255.255.255.0,
>> gw=128.224.149.1,
>>      host=yosemite, domain=, nis-domain=(none),
>>      bootserver=255.255.255.255, rootserver=128.224.149.6, rootpath=
>> Looking up port of RPC 100003/2 on 128.224.149.6
>> Looking up port of RPC 100005/1 on 128.224.149.6
>> VFS: Mounted root (nfs filesystem).
>> Freeing unused kernel memory: 152k init
>> scsi 0:0:0:0: Direct-Access     Kingston DataTraveler 2.0 6.16 PQ: 0
>> ANSI: 0 CCS
>> sd 0:0:0:0: [sda] 244735 512-byte hardware sectors (125 MB)
>> sd 0:0:0:0: [sda] Write Protect is off
>> sd 0:0:0:0: [sda] Mode Sense: 45 00 00 08
>> sd 0:0:0:0: [sda] Assuming drive cache: write through
>> sd 0:0:0:0: [sda] 244735 512-byte hardware sectors (125 MB)
>> sd 0:0:0:0: [sda] Write Protect is off
>> sd 0:0:0:0: [sda] Mode Sense: 45 00 00 08
>> sd 0:0:0:0: [sda] Assuming drive cache: write through
>>  sda: sda1
>> sd 0:0:0:0: [sda] Attached SCSI removable disk
>> sd 0:0:0:0: Attached scsi generic sg0 type 0
>> usb-storage: device scan complete
>> irq 25: nobody cared (try booting with the "irqpoll" option)
>> Call Trace:
>> [cf135af0] [c0008820] show_stack+0x48/0x190 (unreliable)
>> [cf135b20] [c003c414] __report_bad_irq+0x34/0xac
>> [cf135b40] [c003c714] note_interrupt+0x288/0x2c8
>> [cf135b70] [c003b818] __do_IRQ+0x104/0x110
>> [cf135b90] [c0006900] do_IRQ+0xbc/0xc0
>> [cf135ba0] [c00020c0] ret_from_except+0x0/0x18
>> [cf135c60] [00000019] 0x19
>> [cf135c90] [c000668c] do_softirq+0x54/0x58
>> [cf135ca0] [c001df40] irq_exit+0x48/0x58
>> [cf135cb0] [c00068b4] do_IRQ+0x70/0xc0
>> [cf135cc0] [c00020c0] ret_from_except+0x0/0x18
>> [cf135d80] [c003c2b4] setup_irq+0x1ac/0x200
>> [cf135da0] [c003c3cc] request_irq+0xc4/0xd8
>> [cf135dd0] [c0122328] rtl8139_open+0x38/0x210
>> [cf135df0] [c0187500] dev_open+0x7c/0xcc
>> [cf135e10] [c0187420] dev_change_flags+0x16c/0x1d0
>> [cf135e30] [c01cbff0] devinet_ioctl+0x604/0x720
>> [cf135ea0] [c01cc1f8] inet_ioctl+0x98/0xbc
>> [cf135eb0] [c0179328] sock_ioctl+0x60/0x260
>> [cf135ed0] [c006c360] do_ioctl+0x38/0x84
>> [cf135ee0] [c006c438] vfs_ioctl+0x8c/0x40c
>> [cf135f10] [c006c7f8] sys_ioctl+0x40/0x74
>> [cf135f40] [c0001a84] ret_from_syscall+0x0/0x3c
>> handlers:
>> [<c0122bd4>] (rtl8139_interrupt+0x0/0x52c)
>> Disabling IRQ #25
>> eth2: link up, 100Mbps, full-duplex, lpa 0x45E1
>>
>>
>> Who can give some advice?
>>
>> Thanks.
>> BRs,
>> Andrew.
>>
>>
>> _______________________________________________
>> Linuxppc-dev mailing list
>> Linuxppc-dev@ozlabs.org
>> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
> Looks like wrong external interrupt settings (trigger/level) for PCI
> interrupt.
>

^ permalink raw reply

* Re: [PATCH 1/2] qemu platform, v2
From: Milton Miller @ 2007-09-24  9:48 UTC (permalink / raw)
  To: Christoph Hellwig; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <20070924074602.GA19514@lst.de>

On Sep 24, 2007, at 2:46 AM, Christoph Hellwig wrote:
> On Mon, Sep 24, 2007 at 02:00:47PM +1000, David Gibson wrote:
>> Basically because PReP support doesn't work under arch/powerpc.
>> Getting it working properly is something that should happen, but will
>> take a while.  In the meantime, getting something that's sufficient to
>> get working under just qemu's version of prep, without using the
>> abominable openhackware is a quicker path to a usable arch/powerpc
>> kernel under qemu.
>
> Sounds fair.  Care to add something like this to the Kconfig help
> text?

I suppose I could, but actually I wasn't asking for the two qemu 
patches to be merged.  Instead I was posting "here's something that 
provides minimal function for me, hope you can use it too".  For 
instance, someone should track down pci memory so that ohci and/or 
video works.  Then test the isa ne2ks, or better yet get qemu to change 
them to pci (except then it only works on the latest qemu).

I didn't put it under prep because it could be changed for the other 
qemu platforms and doesn't use any thing that makes the machine prep 
other than some memory map information.  I kept prep because I didn't 
want to deal with io to the scc on b&w G3, the other long-term platform 
(or with hackware to see if that would just boot as pmac).

milton

^ permalink raw reply

* [PATCH v2] bootwrapper: adds cuboot for MPC7448HPC2 platform
From: Zang Roy-r61911 @ 2007-09-24 10:31 UTC (permalink / raw)
  To: Paul Mackerras; +Cc: linuxppc-dev list, David Gibson
In-Reply-To: <1184144056.23579.16.camel@localhost.localdomain>

From: Roy Zang <tie-fei.zang@freescale.com>

This patch adds cuboot support for MPC7448HPC2 platform.
The cuImage can be used with legacy u-boot without FDT support.

Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
---
This is the third time for me to generate the patch.
I do not get any negative comment since my previous commit .
Hope your guys can pick it up and merge it into 2.6.24.
The original were pasted at:
http://ozlabs.org/pipermail/linuxppc-dev/2007-May/036834.html
http://ozlabs.org/pipermail/linuxppc-dev/2007-July/038952.html

Cheers

 arch/powerpc/boot/Makefile                 |    3 +-
 arch/powerpc/boot/cuboot-hpc2.c            |   48 ++++++++++++++++++++++++++++
 arch/powerpc/boot/dts/mpc7448hpc2.dts      |    5 +++
 arch/powerpc/platforms/embedded6xx/Kconfig |    1 +
 4 files changed, 56 insertions(+), 1 deletions(-)
 create mode 100644 arch/powerpc/boot/cuboot-hpc2.c

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index cffef14..6ed1415 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -49,7 +49,7 @@ src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
 src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
 		cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
 		ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
-		cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c
+		cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-hpc2.c
 src-boot := $(src-wlib) $(src-plat) empty.c
 
 src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -146,6 +146,7 @@ image-$(CONFIG_8260)			+= cuImage.pq2
 image-$(CONFIG_PPC_83xx)		+= cuImage.83xx
 image-$(CONFIG_PPC_85xx)		+= cuImage.85xx
 image-$(CONFIG_EBONY)			+= treeImage.ebony cuImage.ebony
+image-$(CONFIG_MPC7448HPC2)		+= cuImage.hpc2
 image-$(CONFIG_BAMBOO)			+= treeImage.bamboo
 image-$(CONFIG_SEQUOIA)			+= cuImage.sequoia
 image-$(CONFIG_WALNUT)			+= treeImage.walnut
diff --git a/arch/powerpc/boot/cuboot-hpc2.c b/arch/powerpc/boot/cuboot-hpc2.c
new file mode 100644
index 0000000..d333898
--- /dev/null
+++ b/arch/powerpc/boot/cuboot-hpc2.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Freescale Semiconductor, Inc. All rights reserved.
+ *
+ * Author: Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * Description:
+ * Old U-boot compatibility for mpc7448hpc2 board
+ * Based on the code of Scott Wood <scottwood@freescale.com>
+ * for 83xx and 85xx.
+ *
+ * This 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.
+ *
+ */
+
+#include "ops.h"
+#include "stdio.h"
+#include "cuboot.h"
+
+#define TARGET_HAS_ETH1
+#include "ppcboot.h"
+
+static bd_t bd;
+extern char _dtb_start[], _dtb_end[];
+
+static void platform_fixups(void)
+{
+	void *tsi;
+
+	dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
+	dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
+	dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq);
+	tsi = find_node_by_devtype(NULL, "tsi-bridge");
+	if (tsi)
+		setprop(tsi, "bus-frequency", &bd.bi_busfreq,
+			sizeof(bd.bi_busfreq));
+}
+
+void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
+		unsigned long r6, unsigned long r7)
+{
+	CUBOOT_INIT();
+	ft_init(_dtb_start, _dtb_end - _dtb_start, 32);
+	serial_console_init();
+	platform_ops.fixups = platform_fixups;
+}
diff --git a/arch/powerpc/boot/dts/mpc7448hpc2.dts b/arch/powerpc/boot/dts/mpc7448hpc2.dts
index 70e8a2e..0b58136 100644
--- a/arch/powerpc/boot/dts/mpc7448hpc2.dts
+++ b/arch/powerpc/boot/dts/mpc7448hpc2.dts
@@ -79,6 +79,7 @@
 		};
 
 		ethernet@6200 {
+			linux,network-index = <0>;
 			#size-cells = <0>;
 			device_type = "network";
 			compatible = "tsi109-ethernet", "tsi108-ethernet";
@@ -91,6 +92,7 @@
 		};
 
 		ethernet@6600 {
+			linux,network-index = <1>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 			device_type = "network";
@@ -184,5 +186,8 @@
 			};
 		};
 	};
+	chosen {
+		linux,stdout-path = "/tsi108@c0000000/serial@7808";
+	};
 
 };
diff --git a/arch/powerpc/platforms/embedded6xx/Kconfig b/arch/powerpc/platforms/embedded6xx/Kconfig
index 2d12f77..6d10e84 100644
--- a/arch/powerpc/platforms/embedded6xx/Kconfig
+++ b/arch/powerpc/platforms/embedded6xx/Kconfig
@@ -20,6 +20,7 @@ config MPC7448HPC2
 	select TSI108_BRIDGE
 	select DEFAULT_UIMAGE
 	select PPC_UDBG_16550
+	select WANT_DEVICE_TREE
 	help
 	  Select MPC7448HPC2 if configuring for Freescale MPC7448HPC2 (Taiga)
 	  platform
-- 
1.5.2

^ permalink raw reply related


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