Work at SourceForge, help us to make it a better place! We have an immediate need for a Support Technician in our San Francisco or Denver office.

Close

Diff of /arch/powerpc/platforms/embedded6xx/wii.c [3f1531] .. [aa2218] Maximize Restore

  Switch to side-by-side view

--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/kexec.h>
+#include <linux/exi.h>
 
 #include <asm/io.h>
 #include <asm/machdep.h>
@@ -32,18 +33,26 @@
 
 static void wii_restart(char *cmd)
 {
+	local_irq_disable();
+
+	/* try first to launch The Homebrew Channel... */
+	starlet_es_reload_ios_and_launch(STARLET_TITLE_HBC);
+	/* ..and if that fails, try an assisted restart */
 	starlet_stm_restart();
-	local_irq_disable();
-	/* spin until power button pressed */
+
+	/* fallback to spinning until the power button pressed */
 	for (;;)
 		cpu_relax();
 }
 
 static void wii_power_off(void)
 {
+	local_irq_disable();
+
+	/* try an assisted poweroff */
 	starlet_stm_power_off();
-	local_irq_disable();
-	/* spin until power button pressed */
+
+	/* fallback to spinning until the power button pressed */
 	for (;;)
 		cpu_relax();
 }
@@ -83,13 +92,77 @@
 #ifdef CONFIG_KEXEC
 static void wii_shutdown(void)
 {
-	/* currently not used */
+	exi_quiesce();
+	flipper_quiesce();
 }
 
-static int wii_kexec_prepare(struct kimage *image)
+static int restore_lowmem_stub(struct kimage *image)
 {
-	return 0;
+	struct device_node *node;
+	struct resource res;
+	const unsigned long *prop;
+	unsigned long dst, src;
+	size_t size;
+	int error;
+
+	node = of_find_node_by_name(NULL, "lowmem-stub");
+	if (!node) {
+		printk(KERN_ERR "unable to find node %s\n", "lowmem-stub");
+		error = -ENODEV;
+		goto out;
+	}
+
+	error = of_address_to_resource(node, 0, &res);
+	if (error) {
+		printk(KERN_ERR "no lowmem-stub range found\n");
+		goto out_put;
+	}
+	dst = res.start;
+	size = res.end - res.start + 1;
+
+	prop = of_get_property(node, "save-area", NULL);
+	if (!prop) {
+		printk(KERN_ERR "unable to find %s property\n", "save-area");
+		error = -EINVAL;
+		goto out_put;
+	}
+	src = *prop;
+
+	printk(KERN_DEBUG "lowmem-stub: preparing restore from %08lX to %08lX"
+		" (%u bytes)\n", src, dst, size);
+
+	/* schedule a copy of the lowmem stub to its original location */
+	error = kimage_add_preserved_region(image, dst, src, PAGE_ALIGN(size));
+
+out_put:
+	of_node_put(node);
+out:
+	return error;
 }
+
+static int wii_machine_kexec_prepare(struct kimage *image)
+{
+	int error;
+
+	error = restore_lowmem_stub(image);
+	if (error)
+		printk(KERN_ERR "%s: error %d\n", __func__, error);
+	return error;
+}
+
+static void wii_machine_kexec(struct kimage *image)
+{
+	local_irq_disable();
+
+	/*
+	 * Reload IOS to make sure that I/O resources are freed before
+	 * the final kexec phase.
+ 	 */
+	starlet_es_reload_ios_and_discard();
+
+	default_machine_kexec(image);
+}
+
 #endif /* CONFIG_KEXEC */
 
 
@@ -108,8 +181,8 @@
 	.progress		= udbg_progress,
 #ifdef CONFIG_KEXEC
 	.machine_shutdown	= wii_shutdown,
-	.machine_kexec_prepare	= wii_kexec_prepare,
-	.machine_kexec		= default_machine_kexec,
+	.machine_kexec_prepare	= wii_machine_kexec_prepare,
+	.machine_kexec		= wii_machine_kexec,
 #endif
 };