X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fchar%2Fsnsc_event.c;h=2f56e8c54897d5c55ca1caec974c95e43c787fd6;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=baaa365285fa973776beddcb0ae5c09389ffbe65;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/drivers/char/snsc_event.c b/drivers/char/snsc_event.c index baaa36528..2f56e8c54 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. */ /* @@ -36,7 +36,7 @@ DECLARE_TASKLET(sn_sysctl_event, scdrv_event, 0); * destination. */ static irqreturn_t -scdrv_event_interrupt(int irq, void *subch_data, struct pt_regs *regs) +scdrv_event_interrupt(int irq, void *subch_data) { struct subch_data_s *sd = subch_data; unsigned long flags; @@ -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,25 +200,27 @@ 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; - /* give a SIGPWR signal to init proc */ + if (snsc_shutting_down) + return; - /* first find init's task */ - read_lock(&tasklist_lock); - for_each_process(p) { - if (p->pid == 1) - break; - } - if (p) { /* we found init's task */ - printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n"); - 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); - } - read_unlock(&tasklist_lock); + 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 */ + kill_cad_pid(SIGPWR, 0); } else { /* print to system log */ printk("%s|$(0x%x)%s\n", severity, esp_code, desc); @@ -271,7 +274,7 @@ scdrv_event_init(struct sysctl_data_s *scd) { 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__); @@ -279,7 +282,6 @@ scdrv_event_init(struct sysctl_data_s *scd) } /* 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); @@ -295,7 +297,7 @@ scdrv_event_init(struct sysctl_data_s *scd) /* hook event subchannel up to the system controller interrupt */ rv = request_irq(SGI_UART_VECTOR, scdrv_event_interrupt, - SA_SHIRQ | SA_INTERRUPT, + IRQF_SHARED | IRQF_DISABLED, "system controller events", event_sd); if (rv) { printk(KERN_WARNING "%s: irq request failed (%d)\n", @@ -305,5 +307,3 @@ scdrv_event_init(struct sysctl_data_s *scd) return; } } - -