aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/snsc.h5
-rw-r--r--drivers/char/snsc_event.c32
-rw-r--r--drivers/sn/ioc4.c41
3 files changed, 46 insertions, 32 deletions
diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h
index a9efc13cc858..8a98169b60c1 100644
--- a/drivers/char/snsc.h
+++ b/drivers/char/snsc.h
@@ -5,7 +5,7 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. 8 * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
9 */ 9 */
10 10
11/* 11/*
@@ -70,6 +70,9 @@ struct sysctl_data_s {
70#define EV_CLASS_TEST_WARNING 0x6000ul 70#define EV_CLASS_TEST_WARNING 0x6000ul
71#define EV_CLASS_PWRD_NOTIFY 0x8000ul 71#define EV_CLASS_PWRD_NOTIFY 0x8000ul
72 72
73/* ENV class codes */
74#define ENV_PWRDN_PEND 0x4101ul
75
73#define EV_SEVERITY_POWER_STABLE 0x0000ul 76#define EV_SEVERITY_POWER_STABLE 0x0000ul
74#define EV_SEVERITY_POWER_LOW_WARNING 0x0100ul 77#define EV_SEVERITY_POWER_LOW_WARNING 0x0100ul
75#define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul 78#define EV_SEVERITY_POWER_HIGH_WARNING 0x0200ul
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 @@
5 * License. See the file "COPYING" in the main directory of this archive 5 * License. See the file "COPYING" in the main directory of this archive
6 * for more details. 6 * for more details.
7 * 7 *
8 * Copyright (C) 2004 Silicon Graphics, Inc. All rights reserved. 8 * Copyright (C) 2004-2006 Silicon Graphics, Inc. All rights reserved.
9 */ 9 */
10 10
11/* 11/*
@@ -187,7 +187,8 @@ scdrv_event_severity(int code)
187static void 187static void
188scdrv_dispatch_event(char *event, int len) 188scdrv_dispatch_event(char *event, int len)
189{ 189{
190 int code, esp_code, src; 190 static int snsc_shutting_down = 0;
191 int code, esp_code, src, class;
191 char desc[CHUNKSIZE]; 192 char desc[CHUNKSIZE];
192 char *severity; 193 char *severity;
193 194
@@ -199,9 +200,25 @@ scdrv_dispatch_event(char *event, int len)
199 /* how urgent is the message? */ 200 /* how urgent is the message? */
200 severity = scdrv_event_severity(code); 201 severity = scdrv_event_severity(code);
201 202
202 if ((code & EV_CLASS_MASK) == EV_CLASS_PWRD_NOTIFY) { 203 class = (code & EV_CLASS_MASK);
204
205 if (class == EV_CLASS_PWRD_NOTIFY || code == ENV_PWRDN_PEND) {
203 struct task_struct *p; 206 struct task_struct *p;
204 207
208 if (snsc_shutting_down)
209 return;
210
211 snsc_shutting_down = 1;
212
213 /* give a message for each type of event */
214 if (class == EV_CLASS_PWRD_NOTIFY)
215 printk(KERN_NOTICE "Power off indication received."
216 " Sending SIGPWR to init...\n");
217 else if (code == ENV_PWRDN_PEND)
218 printk(KERN_CRIT "WARNING: Shutting down the system"
219 " due to a critical environmental condition."
220 " Sending SIGPWR to init...\n");
221
205 /* give a SIGPWR signal to init proc */ 222 /* give a SIGPWR signal to init proc */
206 223
207 /* first find init's task */ 224 /* first find init's task */
@@ -210,12 +227,11 @@ scdrv_dispatch_event(char *event, int len)
210 if (p->pid == 1) 227 if (p->pid == 1)
211 break; 228 break;
212 } 229 }
213 if (p) { /* we found init's task */ 230 if (p) {
214 printk(KERN_EMERG "Power off indication received. Initiating power fail sequence...\n");
215 force_sig(SIGPWR, p); 231 force_sig(SIGPWR, p);
216 } else { /* failed to find init's task - just give message(s) */ 232 } else {
217 printk(KERN_WARNING "Failed to find init proc to handle power off!\n"); 233 printk(KERN_ERR "Failed to signal init!\n");
218 printk("%s|$(0x%x)%s\n", severity, esp_code, desc); 234 snsc_shutting_down = 0; /* so can try again (?) */
219 } 235 }
220 read_unlock(&tasklist_lock); 236 read_unlock(&tasklist_lock);
221 } else { 237 } else {
diff --git a/drivers/sn/ioc4.c b/drivers/sn/ioc4.c
index ea75b3d0612b..67140a5804f5 100644
--- a/drivers/sn/ioc4.c
+++ b/drivers/sn/ioc4.c
@@ -31,7 +31,7 @@
31#include <linux/ioc4.h> 31#include <linux/ioc4.h>
32#include <linux/mmtimer.h> 32#include <linux/mmtimer.h>
33#include <linux/rtc.h> 33#include <linux/rtc.h>
34#include <linux/rwsem.h> 34#include <linux/mutex.h>
35#include <asm/sn/addrs.h> 35#include <asm/sn/addrs.h>
36#include <asm/sn/clksupport.h> 36#include <asm/sn/clksupport.h>
37#include <asm/sn/shub_mmr.h> 37#include <asm/sn/shub_mmr.h>
@@ -54,11 +54,10 @@
54 * Submodule management * 54 * Submodule management *
55 ************************/ 55 ************************/
56 56
57static LIST_HEAD(ioc4_devices); 57static DEFINE_MUTEX(ioc4_mutex);
58static DECLARE_RWSEM(ioc4_devices_rwsem);
59 58
59static LIST_HEAD(ioc4_devices);
60static LIST_HEAD(ioc4_submodules); 60static LIST_HEAD(ioc4_submodules);
61static DECLARE_RWSEM(ioc4_submodules_rwsem);
62 61
63/* Register an IOC4 submodule */ 62/* Register an IOC4 submodule */
64int 63int
@@ -66,15 +65,13 @@ ioc4_register_submodule(struct ioc4_submodule *is)
66{ 65{
67 struct ioc4_driver_data *idd; 66 struct ioc4_driver_data *idd;
68 67
69 down_write(&ioc4_submodules_rwsem); 68 mutex_lock(&ioc4_mutex);
70 list_add(&is->is_list, &ioc4_submodules); 69 list_add(&is->is_list, &ioc4_submodules);
71 up_write(&ioc4_submodules_rwsem);
72 70
73 /* Initialize submodule for each IOC4 */ 71 /* Initialize submodule for each IOC4 */
74 if (!is->is_probe) 72 if (!is->is_probe)
75 return 0; 73 goto out;
76 74
77 down_read(&ioc4_devices_rwsem);
78 list_for_each_entry(idd, &ioc4_devices, idd_list) { 75 list_for_each_entry(idd, &ioc4_devices, idd_list) {
79 if (is->is_probe(idd)) { 76 if (is->is_probe(idd)) {
80 printk(KERN_WARNING 77 printk(KERN_WARNING
@@ -84,8 +81,8 @@ ioc4_register_submodule(struct ioc4_submodule *is)
84 pci_name(idd->idd_pdev)); 81 pci_name(idd->idd_pdev));
85 } 82 }
86 } 83 }
87 up_read(&ioc4_devices_rwsem); 84 out:
88 85 mutex_unlock(&ioc4_mutex);
89 return 0; 86 return 0;
90} 87}
91 88
@@ -95,15 +92,13 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
95{ 92{
96 struct ioc4_driver_data *idd; 93 struct ioc4_driver_data *idd;
97 94
98 down_write(&ioc4_submodules_rwsem); 95 mutex_lock(&ioc4_mutex);
99 list_del(&is->is_list); 96 list_del(&is->is_list);
100 up_write(&ioc4_submodules_rwsem);
101 97
102 /* Remove submodule for each IOC4 */ 98 /* Remove submodule for each IOC4 */
103 if (!is->is_remove) 99 if (!is->is_remove)
104 return; 100 goto out;
105 101
106 down_read(&ioc4_devices_rwsem);
107 list_for_each_entry(idd, &ioc4_devices, idd_list) { 102 list_for_each_entry(idd, &ioc4_devices, idd_list) {
108 if (is->is_remove(idd)) { 103 if (is->is_remove(idd)) {
109 printk(KERN_WARNING 104 printk(KERN_WARNING
@@ -113,7 +108,8 @@ ioc4_unregister_submodule(struct ioc4_submodule *is)
113 pci_name(idd->idd_pdev)); 108 pci_name(idd->idd_pdev));
114 } 109 }
115 } 110 }
116 up_read(&ioc4_devices_rwsem); 111 out:
112 mutex_unlock(&ioc4_mutex);
117} 113}
118 114
119/********************* 115/*********************
@@ -312,12 +308,11 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
312 /* Track PCI-device specific data */ 308 /* Track PCI-device specific data */
313 idd->idd_serial_data = NULL; 309 idd->idd_serial_data = NULL;
314 pci_set_drvdata(idd->idd_pdev, idd); 310 pci_set_drvdata(idd->idd_pdev, idd);
315 down_write(&ioc4_devices_rwsem); 311
312 mutex_lock(&ioc4_mutex);
316 list_add(&idd->idd_list, &ioc4_devices); 313 list_add(&idd->idd_list, &ioc4_devices);
317 up_write(&ioc4_devices_rwsem);
318 314
319 /* Add this IOC4 to all submodules */ 315 /* Add this IOC4 to all submodules */
320 down_read(&ioc4_submodules_rwsem);
321 list_for_each_entry(is, &ioc4_submodules, is_list) { 316 list_for_each_entry(is, &ioc4_submodules, is_list) {
322 if (is->is_probe && is->is_probe(idd)) { 317 if (is->is_probe && is->is_probe(idd)) {
323 printk(KERN_WARNING 318 printk(KERN_WARNING
@@ -327,7 +322,7 @@ ioc4_probe(struct pci_dev *pdev, const struct pci_device_id *pci_id)
327 pci_name(idd->idd_pdev)); 322 pci_name(idd->idd_pdev));
328 } 323 }
329 } 324 }
330 up_read(&ioc4_submodules_rwsem); 325 mutex_unlock(&ioc4_mutex);
331 326
332 return 0; 327 return 0;
333 328
@@ -351,7 +346,7 @@ ioc4_remove(struct pci_dev *pdev)
351 idd = pci_get_drvdata(pdev); 346 idd = pci_get_drvdata(pdev);
352 347
353 /* Remove this IOC4 from all submodules */ 348 /* Remove this IOC4 from all submodules */
354 down_read(&ioc4_submodules_rwsem); 349 mutex_lock(&ioc4_mutex);
355 list_for_each_entry(is, &ioc4_submodules, is_list) { 350 list_for_each_entry(is, &ioc4_submodules, is_list) {
356 if (is->is_remove && is->is_remove(idd)) { 351 if (is->is_remove && is->is_remove(idd)) {
357 printk(KERN_WARNING 352 printk(KERN_WARNING
@@ -361,7 +356,7 @@ ioc4_remove(struct pci_dev *pdev)
361 pci_name(idd->idd_pdev)); 356 pci_name(idd->idd_pdev));
362 } 357 }
363 } 358 }
364 up_read(&ioc4_submodules_rwsem); 359 mutex_unlock(&ioc4_mutex);
365 360
366 /* Release resources */ 361 /* Release resources */
367 iounmap(idd->idd_misc_regs); 362 iounmap(idd->idd_misc_regs);
@@ -377,9 +372,9 @@ ioc4_remove(struct pci_dev *pdev)
377 pci_disable_device(pdev); 372 pci_disable_device(pdev);
378 373
379 /* Remove and free driver data */ 374 /* Remove and free driver data */
380 down_write(&ioc4_devices_rwsem); 375 mutex_lock(&ioc4_mutex);
381 list_del(&idd->idd_list); 376 list_del(&idd->idd_list);
382 up_write(&ioc4_devices_rwsem); 377 mutex_unlock(&ioc4_mutex);
383 kfree(idd); 378 kfree(idd);
384} 379}
385 380