linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1
@ 2001-08-06 21:03 David Monniaux
  2001-08-09  7:02 ` Stephen Rothwell
  0 siblings, 1 reply; 6+ messages in thread
From: David Monniaux @ 2001-08-06 21:03 UTC (permalink / raw)
  To: linux-kernel

Dear all,

I have an Athlon on an ASUS A7V133.
This machine powers off perfectly using a stock RedHat 7.1 kernel (2.4.2).
However, it refuses to power off with 2.4.7, with all APM options set
correctly (including power off in real mode).

Now for the funny part: copying the 2.4.2 apm.c to the 2.4.7 and
recompiling yielded a working poweroff. So *something* has been broken
between 2.4.2 and 2.4.7 with APM poweroff. :-)

-- 
David Monniaux            http://www.di.ens.fr/~monniaux
Laboratoire d'informatique de l'École Normale Supérieure,
Paris, France

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

* Re: APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1
  2001-08-06 21:03 APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1 David Monniaux
@ 2001-08-09  7:02 ` Stephen Rothwell
  2001-08-09  7:34   ` Riley Williams
  2001-08-13  7:42   ` Stephen Rothwell
  0 siblings, 2 replies; 6+ messages in thread
From: Stephen Rothwell @ 2001-08-09  7:02 UTC (permalink / raw)
  To: David Monniaux; +Cc: linux-kernel, sfr

Hi David,

On 6 Aug 2001 23:03:35 +0200 David Monniaux wrote:
> 
> I have an Athlon on an ASUS A7V133.
> This machine powers off perfectly using a stock RedHat 7.1 kernel (2.4.2).
> However, it refuses to power off with 2.4.7, with all APM options set
> correctly (including power off in real mode).
> 
> Now for the funny part: copying the 2.4.2 apm.c to the 2.4.7 and
> recompiling yielded a working poweroff. So *something* has been broken
> between 2.4.2 and 2.4.7 with APM poweroff. :-)

So, is this a pristine 2.4.2?  Or is it a RH patched one?  I have just
looked at the differences in arch/i386/kernel/apm.c between 2.4.2 and
2.4.7.  The only differences are in comments and to allow one more
kernel command line option. i.e. there is nothing that should make APM
behave differently.

Could you send me a diff between the two versions of apm.c, please?

Cheers,
Stephen Rothwell
IBM Linux Technology Centre, Canberra

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

* Re: APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1
  2001-08-09  7:02 ` Stephen Rothwell
@ 2001-08-09  7:34   ` Riley Williams
  2001-08-09  8:09     ` Alan Cox
  2001-08-13  7:42   ` Stephen Rothwell
  1 sibling, 1 reply; 6+ messages in thread
From: Riley Williams @ 2001-08-09  7:34 UTC (permalink / raw)
  To: Stephen Rothwell; +Cc: David Monniaux, Linux Kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1416 bytes --]

Hi Stephen.

 >> I have an Athlon on an ASUS A7V133.

 >> This machine powers off perfectly using a stock RedHat 7.1
 >> kernel (2.4.2). However, it refuses to power off with 2.4.7,
 >> with all APM options set correctly (including power off in real
 >> mode).

 >> Now for the funny part: copying the 2.4.2 apm.c to the 2.4.7 and
 >> recompiling yielded a working poweroff. So *something* has been
 >> broken between 2.4.2 and 2.4.7 with APM poweroff. :-)

 > So, is this a pristine 2.4.2? Or is it a RH patched one? I have
 > just looked at the differences in arch/i386/kernel/apm.c between
 > 2.4.2 and 2.4.7. The only differences are in comments and to
 > allow one more kernel command line option. i.e. there is nothing
 > that should make APM behave differently.

 > Could you send me a diff between the two versions of apm.c, please?

I have to admit that your comments made me wonder exactly what patches
RedHat have applied to the kernel and, as I have the 7.1 CD's to hand,
I put the 7.1 source CD in my drive and installed the relevant source
RPM therefrom. There are 227 patches listed therein, which is way too
many IMHO, and some of them clearly need to be considered for the
generic kernel.

Of the many patches theein, the enclosed TWO are the only ones that
touch apm.c so they are the patches you may need to consider. I'd
certainly be interested in your comments thereon.

Best wishes from Riley.

[-- Attachment #2: SysRQ Registration patch --]
[-- Type: TEXT/PLAIN, Size: 23085 bytes --]

diff -u -r --new-file linux/Documentation/sysrq.txt bryce/Documentation/sysrq.txt
--- linux/Documentation/sysrq.txt	Fri Mar 30 18:41:17 2001
+++ bryce/Documentation/sysrq.txt	Fri Mar 30 19:03:14 2001
@@ -126,14 +126,55 @@
 boot script. Oh, and by the way, you exit 'showkey' by not typing anything
 for ten seconds.
 
+*  I want to add SysRQ key events to a module, how does it work?
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In order to register a basic function with the table, you must first include
+the header 'include/linux/sysrq.h', this will define everything else you need.
+Next, you must create a sysrq_key_op struct, and populate it with A) the key
+handler function you will use, B) a help_msg string, that will print when SysRQ
+prints help, and C) an action_msg string, that will print right before your
+handler is called. Your handler must conform to the protoype in 'sysrq.h'.
+
+After the sysrq_key_op is created, you can call the macro 
+REGISTER_SYSRQ_KEY(int key, struct sysrq_key_op *op_p) that is defined in
+sysrq.h, this will register the operation pointed to by 'op_p' at table
+key 'key', if that slot in the table is blank. At module unload time, you must
+call the macro UNREGISTER_SYSRQ_KEY(int key, struct sysrq_key_op *op_p), which
+will remove the key op pointed to by 'op_p' from the key 'key', if and only if
+it is currently registered in that slot. This is in case the slot has been
+overwritten since you registered it.
+
+The Magic SysRQ system works by registering key operations against a key op
+lookup table, which is defined in 'drivers/char/sysrq.c'. This key table has
+a number of operations registered into it at compile time, but is mutable,
+and 4 functions are exported for interface to it: __sysrq_lock_table,
+__sysrq_unlock_table, __sysrq_get_key_op, and __sysrq_put_key_op. The
+functions __sysrq_swap_key_ops and __sysrq_swap_key_ops_nolock are defined
+in the header itself, and the REGISTER and UNREGISTER macros are built fromi
+these. More complex (and dangerous!) manipulations of the table are possible
+using these functions, but you must be careful to always lock the table before
+you read or write from it, and to unlock it again when you are done. (And of
+course, to never ever leave an invalid pointer in the table). Null pointers in
+the table are always safe :)
+
+If for some reason you feel the need to call the handle_sysrq function from
+within a function called by handle_sysrq, you must be aware that you are in
+a lock (you are also in an interupt handler, which means don't sleep!), so
+you must call __handle_sysrq_nolock instead.
+
 *  I have more questions, who can I ask?
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 You may feel free to send email to myrdraal@deathsdoor.com, and I will
 respond as soon as possible.
  -Myrdraal
 
+And I'll answer any questions about the registration system you got, also
+responding as soon as possible.
+ -Crutcher
+
 *  Credits
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Written by Mydraal <myrdraal@deathsdoor.com>
 Updated by Adam Sulmicki <adam@cfar.umd.edu>
 Updated by Jeremy M. Dolan <jmd@turbogeek.org> 2001/01/28 10:15:59
+Added to by Crutcher Dunnavant <crutcher@redhat.com>
diff -u -r --new-file linux/arch/i386/kernel/apm.c bryce/arch/i386/kernel/apm.c
--- linux/arch/i386/kernel/apm.c	Fri Mar 30 18:41:20 2001
+++ bryce/arch/i386/kernel/apm.c	Fri Mar 30 18:59:48 2001
@@ -166,6 +166,11 @@
  *
  * [This document is available from Microsoft at:
  *    http://www.microsoft.com/hwdev/busbios/amp_12.htm]
+ *
+ * (c) 2000 Crutcher Dunnavant <crutcher@redhat.com>
+ * changed to use the sysrq-register hack for registering
+ * the power off function called by magic sysrq
+ * based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
 
 #include <linux/config.h>
@@ -191,12 +196,11 @@
 #include <asm/uaccess.h>
 #include <asm/desc.h>
 
+#include <linux/sysrq.h>
+
 extern unsigned long get_cmos_time(void);
 extern void machine_real_restart(unsigned char *, int);
 
-#ifdef CONFIG_MAGIC_SYSRQ
-extern void (*sysrq_power_off)(void);
-#endif
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
 extern int (*console_blank_hook)(int);
 #endif
@@ -673,6 +677,23 @@
 #endif
 }
 
+#ifdef CONFIG_MAGIC_SYSRQ
+/*
+ * Magic sysrq key and handler for the power off function
+ */
+
+void handle_poweroff (int key, struct pt_regs *pt_regs,
+		                        struct kbd_struct *kbd, struct tty_struct *tty) {
+	        apm_power_off();
+}
+struct sysrq_key_op sysrq_poweroff_op = {
+	handler:        handle_poweroff,
+	help_msg:       "Off",
+	action_msg:     "Power Off\n"
+};
+#endif
+
+
 #ifdef CONFIG_APM_DO_ENABLE
 static int apm_enable_power_management(int enable)
 {
@@ -1528,7 +1549,7 @@
 	if (power_off)
 		pm_power_off = apm_power_off;
 #ifdef CONFIG_MAGIC_SYSRQ
-	sysrq_power_off = apm_power_off;
+	REGISTER_SYSRQ_KEY('o',&sysrq_poweroff_op);
 #endif
 	if (smp_num_cpus == 1) {
 #if defined(CONFIG_APM_DISPLAY_BLANK) && defined(CONFIG_VT)
@@ -1727,7 +1748,7 @@
 	misc_deregister(&apm_device);
 	remove_proc_entry("apm", NULL);
 #ifdef CONFIG_MAGIC_SYSRQ
-	sysrq_power_off = NULL;
+	UNREGISTER_SYSRQ_KEY('o',&sysrq_poweroff_op);
 #endif
 	if (power_off)
 		pm_power_off = NULL;
diff -u -r --new-file linux/drivers/char/sysrq.c bryce/drivers/char/sysrq.c
--- linux/drivers/char/sysrq.c	Fri Feb  9 14:30:22 2001
+++ bryce/drivers/char/sysrq.c	Fri Mar 30 18:59:48 2001
@@ -6,6 +6,10 @@
  *
  *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
  *	based on ideas by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>
+ *
+ *	(c) 2000 Crutcher Dunnavant <crutcher@redhat.com>
+ *	overhauled to use key registration
+ *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
 
 #include <linux/config.h>
@@ -24,6 +28,8 @@
 #include <linux/smp_lock.h>
 #include <linux/module.h>
 
+#include <linux/spinlock.h>
+
 #include <asm/ptrace.h>
 
 extern void wakeup_bdflush(int);
@@ -33,133 +39,71 @@
 /* Whether we react on sysrq keys or just ignore them */
 int sysrq_enabled = 1;
 
-/* Machine specific power off function */
-void (*sysrq_power_off)(void);
-
-EXPORT_SYMBOL(sysrq_power_off);
-
-/* Send a signal to all user processes */
+/* Loglevel sysrq handler */
+static void sysrq_handle_loglevel(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	int i;
+	i = key - '0';
+	console_loglevel = 7;
+	printk("%d\n", i);
+	console_loglevel = i;
+}	
+static struct sysrq_key_op sysrq_loglevel_op = {
+	handler:	sysrq_handle_loglevel,
+	help_msg:	"loglevel0-8",
+	action_msg:	"Loglevel set to ",
+};
 
-static void send_sig_all(int sig, int even_init)
-{
-	struct task_struct *p;
 
-	for_each_task(p) {
-		if (p->mm) {				    /* Not swapper nor kernel thread */
-			if (p->pid == 1 && even_init)	    /* Ugly hack to kill init */
-				p->pid = 0x8000;
-			force_sig(sig, p);
-		}
-	}
+/* SAK sysrq handler */
+#ifdef CONFIG_VT
+static void sysrq_handle_SAK(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	if (tty)
+		do_SAK(tty);
+	reset_vc(fg_console);
 }
+static struct sysrq_key_op sysrq_SAK_op = {
+	handler:	sysrq_handle_SAK,
+	help_msg:	"saK",
+	action_msg:	"SAK\n",
+};
+#endif
 
-/*
- * This function is called by the keyboard handler when SysRq is pressed
- * and any other keycode arrives.
- */
 
-void handle_sysrq(int key, struct pt_regs *pt_regs,
-		  struct kbd_struct *kbd, struct tty_struct *tty)
-{
-	int orig_log_level = console_loglevel;
+/* unraw sysrq handler */
+static void sysrq_handle_unraw(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	if (kbd)
+		kbd->kbdmode = VC_XLATE;
+}
+static struct sysrq_key_op sysrq_unraw_op = {
+	handler:	sysrq_handle_unraw,
+	help_msg:	"unRaw",
+	action_msg:	"Keyboard mode set to XLATE\n",
+};
 
-	if (!sysrq_enabled)
-		return;
 
-	if (!key)
-		return;
+/* reboot sysrq handler */
+static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	machine_restart(NULL);
+}
+static struct sysrq_key_op sysrq_reboot_op = {
+	handler:	sysrq_handle_reboot,
+	help_msg:	"reBoot",
+	action_msg:	"Resetting\n",
+};
 
-	console_loglevel = 7;
-	printk(KERN_INFO "SysRq: ");
-	switch (key) {
-	case 'r':					    /* R -- Reset raw mode */
-		if (kbd) {
-			kbd->kbdmode = VC_XLATE;
-			printk("Keyboard mode set to XLATE\n");
-		}
-		break;
-#ifdef CONFIG_VT
-	case 'k':					    /* K -- SAK */
-		printk("SAK\n");
-		if (tty)
-			do_SAK(tty);
-		reset_vc(fg_console);
-		break;
-#endif
-	case 'b':					    /* B -- boot immediately */
-		printk("Resetting\n");
-		machine_restart(NULL);
-		break;
-	case 'o':					    /* O -- power off */
-		if (sysrq_power_off) {
-			printk("Power off\n");
-			sysrq_power_off();
-		}
-		break;
-	case 's':					    /* S -- emergency sync */
-		printk("Emergency Sync\n");
-		emergency_sync_scheduled = EMERG_SYNC;
-		wakeup_bdflush(0);
-		break;
-	case 'u':					    /* U -- emergency remount R/O */
-		printk("Emergency Remount R/O\n");
-		emergency_sync_scheduled = EMERG_REMOUNT;
-		wakeup_bdflush(0);
-		break;
-	case 'p':					    /* P -- show PC */
-		printk("Show Regs\n");
-		if (pt_regs)
-			show_regs(pt_regs);
-		break;
-	case 't':					    /* T -- show task info */
-		printk("Show State\n");
-		show_state();
-		break;
-	case 'm':					    /* M -- show memory info */
-		printk("Show Memory\n");
-		show_mem();
-		break;
-	case '0' ... '9':				    /* 0-9 -- set console logging level */
-		orig_log_level = key - '0';
-		printk("Log level set to %d\n", orig_log_level);
-		break;
-	case 'e':					    /* E -- terminate all user processes */
-		printk("Terminate All Tasks\n");
-		send_sig_all(SIGTERM, 0);
-		orig_log_level = 8;			    /* We probably have killed syslogd */
-		break;
-	case 'i':					    /* I -- kill all user processes */
-		printk("Kill All Tasks\n");
-		send_sig_all(SIGKILL, 0);
-		orig_log_level = 8;
-		break;
-	case 'l':					    /* L -- kill all processes including init */
-		printk("Kill ALL Tasks (even init)\n");
-		send_sig_all(SIGKILL, 1);
-		orig_log_level = 8;
-		break;
-	default:					    /* Unknown: help */
-		if (kbd)
-			printk("unRaw ");
-#ifdef CONFIG_VT
-		if (tty)
-			printk("saK ");
-#endif
-		printk("Boot ");
-		if (sysrq_power_off)
-			printk("Off ");
-		printk("Sync Unmount showPc showTasks showMem loglevel0-8 tErm kIll killalL\n");
-		/* Don't use 'A' as it's handled specially on the Sparc */
-	}
 
-	console_loglevel = orig_log_level;
-}
 
-/* Aux routines for the syncer */
+/* SYNC SYSRQ HANDLERS BLOCK */
 
-static int is_local_disk(kdev_t dev)	    /* Guess if the device is a local hard drive */
-{
-	unsigned int major = MAJOR(dev);
+/* do_emergency_sync helper function */
+/* Guesses if the device is a local hard drive */
+static int is_local_disk(kdev_t dev) {
+	unsigned int major;
+	major = MAJOR(dev);
 
 	switch (major) {
 	case IDE0_MAJOR:
@@ -180,13 +124,17 @@
 	}
 }
 
+/* do_emergency_sync helper function */
 static void go_sync(struct super_block *sb, int remount_flag)
 {
+	int orig_loglevel;
+	orig_loglevel = console_loglevel;
+	console_loglevel = 7;
 	printk(KERN_INFO "%sing device %s ... ",
 	       remount_flag ? "Remount" : "Sync",
 	       kdevname(sb->s_dev));
 
-	if (remount_flag) {				    /* Remount R/O */
+	if (remount_flag) { /* Remount R/O */
 		int ret, flags;
 		struct list_head *p;
 
@@ -216,12 +164,12 @@
 			}
 		} else
 			printk("nothing to do\n");
-	} else {
-		fsync_dev(sb->s_dev);			    /* Sync only */
+	} else { /* Sync only */
+		fsync_dev(sb->s_dev);
 		printk("OK\n");
 	}
+	console_loglevel = orig_loglevel;
 }
-
 /*
  * Emergency Sync or Unmount. We cannot do it directly, so we set a special
  * flag and wake up the bdflush kernel thread which immediately calls this function.
@@ -231,10 +179,10 @@
 
 int emergency_sync_scheduled;
 
-void do_emergency_sync(void)
-{
+void do_emergency_sync(void) {
 	struct super_block *sb;
 	int remount_flag;
+	int orig_loglevel;
 
 	lock_kernel();
 	remount_flag = (emergency_sync_scheduled == EMERG_REMOUNT);
@@ -253,5 +201,270 @@
 			go_sync(sb, remount_flag);
 
 	unlock_kernel();
+
+	orig_loglevel = console_loglevel;
+	console_loglevel = 7;
 	printk(KERN_INFO "Done.\n");
+	console_loglevel = orig_loglevel;
+}
+
+static void sysrq_handle_sync(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	emergency_sync_scheduled = EMERG_SYNC;
+	wakeup_bdflush(0);
 }
+static struct sysrq_key_op sysrq_sync_op = {
+	handler:	sysrq_handle_sync,
+	help_msg:	"Sync",
+	action_msg:	"Emergency Sync\n",
+};
+
+static void sysrq_handle_mountro(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	emergency_sync_scheduled = EMERG_REMOUNT;
+	wakeup_bdflush(0);
+}
+static struct sysrq_key_op sysrq_mountro_op = {
+	handler:	sysrq_handle_mountro,
+	help_msg:	"Unmount",
+	action_msg:	"Emergency Remount R/0\n",
+};
+
+/* END SYNC SYSRQ HANDLERS BLOCK */
+
+
+/* SHOW SYSRQ HANDLERS BLOCK */
+
+static void sysrq_handle_showregs(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	if (pt_regs)
+		show_regs(pt_regs);
+}
+static struct sysrq_key_op sysrq_showregs_op = {
+	handler:	sysrq_handle_showregs,
+	help_msg:	"showPc",
+	action_msg:	"Show Regs\n",
+};
+
+
+static void sysrq_handle_showstate(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	show_state();
+}
+static struct sysrq_key_op sysrq_showstate_op = {
+	handler:	sysrq_handle_showstate,
+	help_msg:	"showTasks",
+	action_msg:	"Show State\n",
+};
+
+
+static void sysrq_handle_showmem(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	show_mem();
+}
+static struct sysrq_key_op sysrq_showmem_op = {
+	handler:	sysrq_handle_showmem,
+	help_msg:	"showMem",
+	action_msg:	"Show Memory\n",
+};
+
+/* SHOW SYSRQ HANDLERS BLOCK */
+
+
+/* SIGNAL SYSRQ HANDLERS BLOCK */
+
+/* signal sysrq helper function
+ * Sends a signal to all user processes */
+static void send_sig_all(int sig, int even_init)
+{
+	struct task_struct *p;
+
+	for_each_task(p) {
+		if (p->mm) { /* Not swapper nor kernel thread */
+			if (p->pid == 1 && even_init)
+				/* Ugly hack to kill init */
+				p->pid = 0x8000;
+			force_sig(sig, p);
+		}
+	}
+}
+
+static void sysrq_handle_term(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	send_sig_all(SIGTERM, 0);
+	console_loglevel = 8;
+}
+static struct sysrq_key_op sysrq_term_op = {
+	handler:	sysrq_handle_term,
+	help_msg:	"tErm",
+	action_msg:	"Terminate All Tasks\n",
+};
+
+static void sysrq_handle_kill(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	send_sig_all(SIGKILL, 0);
+	console_loglevel = 8;
+}
+static struct sysrq_key_op sysrq_kill_op = {
+	handler:	sysrq_handle_kill,
+	help_msg:	"kIll",
+	action_msg:	"Kill All Tasks\n",
+};
+
+static void sysrq_handle_killall(int key, struct pt_regs *pt_regs,
+		struct kbd_struct *kbd, struct tty_struct *tty) {
+	send_sig_all(SIGKILL, 1);
+	console_loglevel = 8;
+}
+static struct sysrq_key_op sysrq_killall_op = {
+	handler:	sysrq_handle_killall,
+	help_msg:	"killalL",
+	action_msg:	"Kill All Tasks (even init)\n",
+};
+
+/* END SIGNAL SYSRQ HANDLERS BLOCK */
+
+
+/* Key Operations table and lock */
+spinlock_t sysrq_key_table_lock = SPIN_LOCK_UNLOCKED;
+#define SYSRQ_KEY_TABLE_LENGTH 36
+static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
+/* 0 */	&sysrq_loglevel_op,
+/* 1 */	&sysrq_loglevel_op,
+/* 2 */	&sysrq_loglevel_op,
+/* 3 */	&sysrq_loglevel_op,
+/* 4 */	&sysrq_loglevel_op,
+/* 5 */	&sysrq_loglevel_op,
+/* 6 */	&sysrq_loglevel_op,
+/* 7 */	&sysrq_loglevel_op,
+/* 8 */	&sysrq_loglevel_op,
+/* 9 */	&sysrq_loglevel_op,
+/* a */	NULL, /* Don't use for system provided sysrqs,
+		 it is handled specially on the spark
+		 and will never arive */
+/* b */	&sysrq_reboot_op,
+/* c */	NULL,
+/* d */	NULL,
+/* e */	&sysrq_term_op,
+/* f */	NULL,
+/* g */	NULL,
+/* h */	NULL,
+/* i */	&sysrq_kill_op,
+/* j */	NULL,
+#ifdef CONFIG_VT
+/* k */	&sysrq_SAK_op,
+#else
+/* k */	NULL,
+#endif
+/* l */	&sysrq_killall_op,
+/* m */	&sysrq_showmem_op,
+/* n */	NULL,
+/* o */	NULL, /* This will often be registered
+		 as 'Off' at init time */
+/* p */	&sysrq_showregs_op,
+/* q */	NULL,
+/* r */	&sysrq_unraw_op,
+/* s */	&sysrq_sync_op,
+/* t */	&sysrq_showstate_op,
+/* u */	&sysrq_mountro_op,
+/* v */	NULL,
+/* w */	NULL,
+/* x */	NULL,
+/* w */	NULL,
+/* z */	NULL
+};
+
+/* key2index calculation, -1 on invalid index */
+static __inline__ int sysrq_key_table_key2index(int key) {
+	int retval;
+	if ((key >= '0') & (key <= '9')) {
+		retval = key - '0';
+	} else if ((key >= 'a') & (key <= 'z')) {
+		retval = key + 10 - 'a';
+	} else {
+		retval = -1;
+	}
+	return retval;
+}
+
+/*
+ * table lock and unlocking functions, exposed to modules
+ */
+
+void __sysrq_lock_table (void) { spin_lock(&sysrq_key_table_lock); }
+
+void __sysrq_unlock_table (void) { spin_unlock(&sysrq_key_table_lock); }
+
+/*
+ * get and put functions for the table, exposed to modules.
+ */
+
+struct sysrq_key_op *__sysrq_get_key_op (int key) {
+        struct sysrq_key_op *op_p;
+        int i;
+	
+	i = sysrq_key_table_key2index(key);
+        op_p = (i == -1) ? NULL : sysrq_key_table[i];
+        return op_p;
+}
+
+void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p) {
+        int i;
+
+	i = sysrq_key_table_key2index(key);
+        if (i != -1)
+                sysrq_key_table[i] = op_p;
+}
+
+/*
+ * This function is called by the keyboard handler when SysRq is pressed
+ * and any other keycode arrives.
+ */
+
+void handle_sysrq(int key, struct pt_regs *pt_regs,
+		  struct kbd_struct *kbd, struct tty_struct *tty) {
+	if (!sysrq_enabled)
+		return;
+
+	__sysrq_lock_table();
+	__handle_sysrq_nolock(key, pt_regs, kbd, tty);
+	__sysrq_unlock_table();
+}
+
+/*
+ * This is the non-locking version of handle_sysrq
+ * It must/can only be called by sysrq key handlers,
+ * as they are inside of the lock
+ */
+
+void __handle_sysrq_nolock(int key, struct pt_regs *pt_regs,
+		  struct kbd_struct *kbd, struct tty_struct *tty) {
+	struct sysrq_key_op *op_p;
+	int orig_log_level;
+	int i, j;
+	
+	if (!sysrq_enabled)
+		return;
+
+	orig_log_level = console_loglevel;
+	console_loglevel = 7;
+	printk(KERN_INFO "SysRq : ");
+
+        op_p = __sysrq_get_key_op(key);
+        if (op_p) {
+                printk ("%s", op_p->action_msg);
+                op_p->handler(key, pt_regs, kbd, tty);
+	} else {
+		printk("HELP : ");
+		/* Only print the help msg once per handler */
+		for (i=0; i<SYSRQ_KEY_TABLE_LENGTH; i++) 
+		if (sysrq_key_table[i]) {
+			for (j=0; sysrq_key_table[i] != sysrq_key_table[j]; j++);
+			if (j == i)
+				printk ("%s ", sysrq_key_table[i]->help_msg);
+		}
+		printk ("\n");
+	}
+	console_loglevel = orig_log_level;
+}
+
diff -u -r --new-file linux/include/linux/sysrq.h bryce/include/linux/sysrq.h
--- linux/include/linux/sysrq.h	Fri Mar 30 18:56:21 2001
+++ bryce/include/linux/sysrq.h	Fri Mar 30 18:59:48 2001
@@ -5,6 +5,10 @@
  *	Linux Magic System Request Key Hacks
  *
  *	(c) 1997 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
+ *
+ *	(c) 2000 Crutcher Dunnavant <crutcher@redhat.com>
+ *	overhauled to use key registration
+ *	based upon discusions in irc://irc.openprojects.net/#kernelnewbies
  */
 
 #include <linux/config.h>
@@ -13,12 +17,64 @@
 struct kbd_struct;
 struct tty_struct;
 
+struct sysrq_key_op {
+	void (*handler)(int, struct pt_regs *,
+			struct kbd_struct *, struct tty_struct *);
+	char *help_msg;
+	char *action_msg;
+};
+
 /* Generic SysRq interface -- you may call it from any device driver, supplying
  * ASCII code of the key, pointer to registers and kbd/tty structs (if they
  * are available -- else NULL's).
  */
 
-void handle_sysrq(int, struct pt_regs *, struct kbd_struct *, struct tty_struct *);
+void handle_sysrq(int, struct pt_regs *,
+		struct kbd_struct *, struct tty_struct *);
+
+
+/* 
+ * Nonlocking version of handle sysrq, used by sysrq handlers that need to
+ * call sysrq handlers
+ */
+
+void __handle_sysrq_nolock(int, struct pt_regs *,
+                struct kbd_struct *, struct tty_struct *);
+
+/*
+ * Sysrq registration manipulation functions
+ */
+
+void __sysrq_lock_table (void);
+void __sysrq_unlock_table (void);
+struct sysrq_key_op *__sysrq_get_key_op (int key);
+void __sysrq_put_key_op (int key, struct sysrq_key_op *op_p);
+
+extern __inline__ int
+__sysrq_swap_key_ops_nolock(int key, struct sysrq_key_op *insert_op_p,
+				struct sysrq_key_op *remove_op_p) {
+	int retval;
+	if (__sysrq_get_key_op(key) == remove_op_p) {
+		__sysrq_put_key_op(key, insert_op_p);
+		retval = 0;
+	} else {
+                retval = -1;
+	}
+	return retval;
+}
+
+extern __inline__ int
+__sysrq_swap_key_ops(int key, struct sysrq_key_op *insert_op_p,
+				struct sysrq_key_op *remove_op_p) {
+	int retval;
+	__sysrq_lock_table();
+	retval = __sysrq_swap_key_ops_nolock(key, insert_op_p, remove_op_p);
+	__sysrq_unlock_table();
+	return retval;
+}
+	
+#define REGISTER_SYSRQ_KEY(KEY, OP_P) __sysrq_swap_key_ops(KEY, OP_P, NULL)
+#define UNREGISTER_SYSRQ_KEY(KEY, OP_P) __sysrq_swap_key_ops(KEY, NULL, OP_P)
 
 /* Deferred actions */
 
diff -u -r --new-file linux/kernel/ksyms.c bryce/kernel/ksyms.c
--- linux/kernel/ksyms.c	Fri Mar 30 18:41:24 2001
+++ bryce/kernel/ksyms.c	Fri Mar 30 19:04:24 2001
@@ -7,6 +7,10 @@
  * - External symbol table support added (December 1994)
  * - Versions on symbols added (December 1994)
  *   by Bjorn Ekwall <bj0rn@blox.se>
+ *
+ *   Added sysrq interface for dynamic sysrq (2000)
+ *   Crutcher Dunnavant <crutcher@redhat.com>
+ *     
  */
 
 #define __KERNEL_SYSCALLS__
@@ -47,6 +51,7 @@
 #include <linux/brlock.h>
 #include <linux/fs.h>
 #include <linux/tty.h>
+#include <linux/sysrq.h>
 #include <asm/checksum.h>
 #include <linux/unistd.h>
 
@@ -559,3 +564,12 @@
 
 EXPORT_SYMBOL(tasklist_lock);
 EXPORT_SYMBOL(pidhash);
+
+/* dynamic sysrq registration */
+EXPORT_SYMBOL(handle_sysrq);
+EXPORT_SYMBOL(__handle_sysrq_nolock);
+EXPORT_SYMBOL(__sysrq_lock_table);
+EXPORT_SYMBOL(__sysrq_unlock_table);
+EXPORT_SYMBOL(__sysrq_get_key_op);
+EXPORT_SYMBOL(__sysrq_put_key_op);
+

[-- Attachment #3: Real mode poweroff patch --]
[-- Type: TEXT/PLAIN, Size: 935 bytes --]

--- linux/arch/i386/kernel/apm.c.org	Tue Feb 13 13:50:48 2001
+++ linux/arch/i386/kernel/apm.c	Tue Feb 13 13:53:13 2001
@@ -343,6 +343,7 @@
 #else
 static int			power_off = 1;
 #endif
+static int			realmode_power_off = 0;
 static int			exit_kapmd;
 static int			kapmd_running;
 
@@ -663,7 +664,10 @@
 	}
 #endif
 #ifdef CONFIG_APM_REAL_MODE_POWER_OFF
-	machine_real_restart(po_bios_call, sizeof(po_bios_call));
+	if (realmode_power_off)
+		machine_real_restart(po_bios_call, sizeof(po_bios_call));
+	else
+		(void) apm_set_power_state(APM_STATE_OFF);
 #else
 	(void) apm_set_power_state(APM_STATE_OFF);
 #endif
@@ -1548,6 +1552,8 @@
 	while ((str != NULL) && (*str != '\0')) {
 		if (strncmp(str, "off", 3) == 0)
 			apm_disabled = 1;
+		if (strncmp(str, "realmode", 8) == 0)
+			realmode_power_off = 1;
 		if (strncmp(str, "on", 2) == 0)
 			apm_disabled = 0;
 		invert = (strncmp(str, "no-", 3) == 0);

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

* Re: APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1
  2001-08-09  7:34   ` Riley Williams
@ 2001-08-09  8:09     ` Alan Cox
  2001-08-09 23:41       ` Riley Williams
  0 siblings, 1 reply; 6+ messages in thread
From: Alan Cox @ 2001-08-09  8:09 UTC (permalink / raw)
  To: Riley Williams; +Cc: Stephen Rothwell, David Monniaux, Linux Kernel

> I put the 7.1 source CD in my drive and installed the relevant source
> RPM therefrom. There are 227 patches listed therein, which is way too
> many IMHO, and some of them clearly need to be considered for the
> generic kernel.

Most of them have been in -ac since the early days (the RH 2.4.2 is closer
to 2.4.3-ac than 2.4.2 in truth) and pushed on to Linus long ago

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

* Re: APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1
  2001-08-09  8:09     ` Alan Cox
@ 2001-08-09 23:41       ` Riley Williams
  0 siblings, 0 replies; 6+ messages in thread
From: Riley Williams @ 2001-08-09 23:41 UTC (permalink / raw)
  To: Alan Cox; +Cc: Stephen Rothwell, David Monniaux, Linux Kernel

Hi Alan.

 >> I put the 7.1 source CD in my drive and installed the relevant
 >> source RPM therefrom. There are 227 patches listed therein,
 >> which is way too many IMHO, and some of them clearly need to be
 >> considered for the generic kernel.

 > Most of them have been in -ac since the early days (the RH 2.4.2
 > is closer to 2.4.3-ac than 2.4.2 in truth) and pushed on to
 > Linus long ago

I guessed as much! However, it appears from the question being asked
that some of them never made it into the latest 2.4 kernel, and
specifically one of the two that I enclosed with that email, if the
complainant's comments and Stephen's replies are both accurate.

Best wishes from Riley.


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

* Re: APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1
  2001-08-09  7:02 ` Stephen Rothwell
  2001-08-09  7:34   ` Riley Williams
@ 2001-08-13  7:42   ` Stephen Rothwell
  1 sibling, 0 replies; 6+ messages in thread
From: Stephen Rothwell @ 2001-08-13  7:42 UTC (permalink / raw)
  To: Riley Williams; +Cc: monniaux, linux-kernel

Hi Riley,

On Thu, 9 Aug 2001 08:34:51 +0100 (BST) Riley Williams <rhw@MemAlpha.CX> wrote:
> 
> Of the many patches theein, the enclosed TWO are the only ones that
> touch apm.c so they are the patches you may need to consider. I'd
> certainly be interested in your comments thereon.

I have seen both these patches.  The first is not relevant (it just changes
how we register a sysreq key).  The second has the effect of NOT using
the real mode power off code unless both CONFIG_APM_REAL_MODE_POWER_OFF
was set at kerne configure time AND "apm=realmode" was specified on the
kernel command line at boot time.

So those having trouble powering off with 2.4.[78] when the Red Hat kernel
did power off, should try building their kernels with
CONFIG_APM_REAL_MODE_POWER_OFF NOT selected.

Cheers,
Stephen Rothwell
IBM OzLabs - Linux Technology Centre

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

end of thread, other threads:[~2001-08-13  7:43 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-08-06 21:03 APM poweroff under Linux 2.4.7 / 2.4.2 RH 7.1 David Monniaux
2001-08-09  7:02 ` Stephen Rothwell
2001-08-09  7:34   ` Riley Williams
2001-08-09  8:09     ` Alan Cox
2001-08-09 23:41       ` Riley Williams
2001-08-13  7:42   ` Stephen Rothwell

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