* 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.
*/
/*
#include <linux/sched.h>
#include <linux/byteorder/generic.h>
#include <asm/sn/sn_sal.h>
+#include <asm/unaligned.h>
#include "snsc.h"
static struct subch_data_s *event_sd;
scdrv_parse_event(char *event, int *src, int *code, int *esp_code, char *desc)
{
char *desc_end;
+ __be32 from_buf;
/* record event source address */
- *src = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *src = be32_to_cpup(&from_buf);
event += 4; /* move on to event code */
/* record the system controller's event code */
- *code = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *code = be32_to_cpup(&from_buf);
event += 4; /* move on to event arguments */
/* how many arguments are in the packet? */
/* not an integer argument, so give up */
return -1;
}
- *esp_code = be32_to_cpup((__be32 *)event);
+ from_buf = get_unaligned((__be32 *)event);
+ *esp_code = be32_to_cpup(&from_buf);
event += 4;
/* parse out the event description */
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;
/* 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 */
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 {
{
int rv;
- event_sd = kmalloc(sizeof (struct subch_data_s), GFP_KERNEL);
+ event_sd = kzalloc(sizeof (struct subch_data_s), GFP_KERNEL);
if (event_sd == NULL) {
printk(KERN_WARNING "%s: couldn't allocate subchannel info"
" for event monitoring\n", __FUNCTION__);
}
/* initialize subch_data_s fields */
- memset(event_sd, 0, sizeof (struct subch_data_s));
event_sd->sd_nasid = scd->scd_nasid;
spin_lock_init(&event_sd->sd_rlock);
return;
}
}
-
-