summaryrefslogtreecommitdiffstats
path: root/drivers/char/snsc_event.c
diff options
context:
space:
mode:
authorAaron Young <ayoung@google.engr.sgi.com>2006-01-23 09:00:51 -0800
committerTony Luck <tony.luck@intel.com>2006-01-26 13:32:26 -0800
commit28ff6b9b2fc01d2c2746c72ce8af1729344fae27 (patch)
tree6209aa2a6416cc7c363ad8c8efef2e15ca7b9b59 /drivers/char/snsc_event.c
parent3ee68c4af3fd7228c1be63254b9f884614f9ebb2 (diff)
downloadlinux-stable-28ff6b9b2fc01d2c2746c72ce8af1729344fae27.tar.gz
linux-stable-28ff6b9b2fc01d2c2746c72ce8af1729344fae27.tar.bz2
linux-stable-28ff6b9b2fc01d2c2746c72ce8af1729344fae27.zip
[IA64-SGI] Handle SC env. powerdown events
Handle system controller power down pending events on SN systems. This allows the system to gracefully shutdown before the system controller removes power due to an adverse environmental condition. Signed-off-by: Aaron Young <ayoung@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'drivers/char/snsc_event.c')
-rw-r--r--drivers/char/snsc_event.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c
index baaa365285fa..a4fa507eed9e 100644
--- a/drivers/char/snsc_event.c
+++ b/drivers/char/snsc_event.c
@@ -5,7 +5,7 @@
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
- * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
*/
/*
@@ -187,7 +187,8 @@ scdrv_event_severity(int code)
static void
scdrv_dispatch_event(char *event, int len)
{
- int code, esp_code, src;
+ static int snsc_shutting_down = 0;
+ int code, esp_code, src, class;
char desc[CHUNKSIZE];
char *severity;
@@ -199,9 +200,25 @@ scdrv_dispatch_event(char *event, int len)
/* how urgent is the message? */
severity = scdrv_event_severity(code);
- if ((code & EV_CLASS_MASK) == EV_CLASS_PWRD_NOTIFY) {
+ class = (code & EV_CLASS_MASK);
+
+ if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) {
struct task_struct *p;
+ if (snsc_shutting_down)
+ return;
+
+ snsc_shutting_down = 1;
+
+ /* give a message for each type of event */
+ if (class == EV_CLASS_PWRD_NOTIFY)
+ printk(KERN_NOTICE "Power off indication received."
+ " Sending SIGPWR to init...\n");
+ else if (code == ENV_PWRDN_PEND)
+ printk(KERN_CRIT "WARNING: Shutting down the system"
+ " due to a critical environmental condition."
+ " Sending SIGPWR to init...\n");
+
/* give a SIGPWR signal to init proc */
/* first find init's task */
@@ -210,12 +227,11 @@ scdrv_dispatch_event(char *event, int len)
if (p->pid == 1)
break;
}
- if (p) { /* we found init's task */
- printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n");
+ if (p) {
force_sig(SIGPWR, p);
- } else { /* failed to find init's task - just give message(s) */
- printk(KERN_WARNING "Failed to find init proc to handle power off!\n");
- printk("%s|$(0x%x)%s\n", severity, esp_code, desc);
+ } else {
+ printk(KERN_ERR "Failed to signal init!\n");
+ snsc_shutting_down = 0; /* so can try again (?) */
}
read_unlock(&tasklist_lock);
} else {