iwpriv (Was: OLPC News 2007-12-30)

David Woodhouse dwmw2 at infradead.org
Tue Jan 1 10:52:29 EST 2008


On Mon, 2007-12-31 at 18:10 +0000, David Woodhouse wrote:
> > An interesting goal would be cleaning up CONFIG_OLPC so that
> > it could be enabled in stock kernels of standard Linux distros.
> 
> I actually see that as a prerequisite for getting the thing upstream.
> And the first step along that path is to stop making it worse.

Let's see if we can repeat history. If experience with the libertas
driver is anything to go by, I predict that by starting to look at the
problem, I will provoke others into a generating a storm of conflicting
patches by attempting to do the same thing themselves¹.

So here's an untested patch to make the reboot fixups slightly more
generic, so that we can easily add our own 'fixup' for the XO in a
fashion which will actually be mergeable upstream.

Untested-but-otherwise-Signed-Off-By: David Woodhouse <dwmw2 at infradead.org>

diff --git a/arch/x86/kernel/reboot_32.c b/arch/x86/kernel/reboot_32.c
index bb1a0f8..dedb1d8 100644
--- a/arch/x86/kernel/reboot_32.c
+++ b/arch/x86/kernel/reboot_32.c
@@ -332,9 +332,7 @@ static void native_machine_shutdown(void)
 #endif
 }
 
-void __attribute__((weak)) mach_reboot_fixups(void)
-{
-}
+void (*mach_reboot_fixup)(void);
 
 static void native_machine_emergency_restart(void)
 {
@@ -347,7 +345,8 @@ static void native_machine_emergency_restart(void)
 		/* rebooting needs to touch the page at absolute addr 0 */
 		*((unsigned short *)__va(0x472)) = reboot_mode;
 		for (;;) {
-			mach_reboot_fixups(); /* for board specific fixups */
+			if (mach_reboot_fixup)
+				mach_reboot_fixup();
 			mach_reboot();
 			/* That didn't work - force a triple fault.. */
 			load_idt(&no_idt);
diff --git a/arch/x86/kernel/reboot_fixups_32.c b/arch/x86/kernel/reboot_fixups_32.c
index f452726..d9607a7 100644
--- a/arch/x86/kernel/reboot_fixups_32.c
+++ b/arch/x86/kernel/reboot_fixups_32.c
@@ -14,16 +14,18 @@
 #include <asm/msr.h>
 #include <asm/geode.h>
 
-static void cs5530a_warm_reset(struct pci_dev *dev)
+static pci_dev *cs5530a_pci_dev;
+
+static void cs5530a_warm_reset(void)
 {
 	/* writing 1 to the reset control register, 0x44 causes the
 	cs5530a to perform a system warm reset */
-	pci_write_config_byte(dev, 0x44, 0x1);
+	pci_write_config_byte(cs5530_pci_dev, 0x44, 0x1);
 	udelay(50); /* shouldn't get here but be safe and spin-a-while */
 	return;
 }
 
-static void cs5536_warm_reset(struct pci_dev *dev)
+static void cs5536_warm_reset(void)
 {
 	/* writing 1 to the LSB of this MSR causes a hard reset */
 	wrmsrl(MSR_DIVIL_SOFT_RESET, 1ULL);
@@ -48,24 +50,23 @@ static struct device_fixup fixups_table[] = {
  * do return, we keep looking and then eventually fall back to the
  * standard mach_reboot on return.
  */
-void mach_reboot_fixups(void)
+int mach_reboot_fixup_setup(void)
 {
 	struct device_fixup *cur;
 	struct pci_dev *dev;
 	int i;
 
-	/* we can be called from sysrq-B code. In such a case it is
-	 * prohibited to dig PCI */
-	if (in_interrupt())
-		return;
-
 	for (i=0; i < ARRAY_SIZE(fixups_table); i++) {
 		cur = &(fixups_table[i]);
 		dev = pci_get_device(cur->vendor, cur->device, NULL);
 		if (!dev)
 			continue;
 
-		cur->reboot_fixup(dev);
+		cs5530a_pci_dev = dev;
+		mach_reboot_fixup = cur->reboot_fixup;
 	}
+	return 0;
 }
 
+subsys_initcall(mach_reboot_fixup_setup);
+
diff --git a/include/asm-x86/reboot_fixups.h b/include/asm-x86/reboot_fixups.h
index 0cb7d87..4f79001 100644
--- a/include/asm-x86/reboot_fixups.h
+++ b/include/asm-x86/reboot_fixups.h
@@ -1,6 +1,6 @@
 #ifndef _LINUX_REBOOT_FIXUPS_H
 #define _LINUX_REBOOT_FIXUPS_H
 
-extern void mach_reboot_fixups(void);
+extern void (*mach_reboot_fixup)(void);
 
 #endif /* _LINUX_REBOOT_FIXUPS_H */

-- 
dwmw2

¹ Only this time I don't actually plan to follow through; I'm relying on
the interference.... 




More information about the Devel mailing list