[parisc-linux-cvs] linux deller
Helge Deller
deller@gmx.de
Thu, 27 Jun 2002 00:23:34 +0200
--Boundary-00=_m7jG9Ny9Z1+7wmF
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: 8bit
Content-Disposition: inline
On Thursday 27 June 2002 00:20, Helge Deller wrote:
> CVSROOT: /var/cvs
> Module name: linux
> Changes by: deller 02/06/26 16:20:32
>
> Modified files:
> . : Makefile
> arch/parisc/kernel: power.c time.c
> include/asm-parisc: irq.h
>
> Log message:
> 2.4.18-pa42:
> - fix a long out-standing reboot-bug:
> - added re-enabling of soft-power switch in the panic notifier chain. This
> allows us now to reboot the machine if we got a panic. This never worked
> before and helps to debug kernel-problems without pulling the power cable.
> Closes bug #94 and similiar bug reports.
> - now use tasklets for checking the soft-power switch instead of a function
> pointer - added full License
--Boundary-00=_m7jG9Ny9Z1+7wmF
Content-Type: text/plain;
charset="iso-8859-1";
name="diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="diff"
Index: Makefile
===================================================================
RCS file: /var/cvs/linux/Makefile,v
retrieving revision 1.312
diff -u -p -r1.312 Makefile
--- Makefile 2002/06/25 20:53:16 1.312
+++ Makefile 2002/06/26 22:14:59
@@ -1,7 +1,7 @@
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 18
-EXTRAVERSION = -pa41
+EXTRAVERSION = -pa42
KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
Index: arch/parisc/kernel/power.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/power.c,v
retrieving revision 1.8
diff -u -p -r1.8 power.c
--- arch/parisc/kernel/power.c 2002/04/22 00:04:10 1.8
+++ arch/parisc/kernel/power.c 2002/06/26 22:14:59
@@ -1,28 +1,46 @@
/*
- * linux/arch/parisc/kernel/power.c
- * HP PARISC soft power switch support driver
+ * linux/arch/parisc/kernel/power.c
+ * HP PARISC soft power switch support driver
*
- * Copyright (C) 2001-2002 Helge Deller <deller@gmx.de>
+ * Copyright (c) 2001-2002 Helge Deller <deller@gmx.de>
+ * All rights reserved.
*
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ *
*
* HINT:
* Support of the soft power switch button may be enabled or disabled at
* runtime through the "/proc/sys/kernel/power" procfs entry.
- *
- */
+ */
-/*
- * TODO:
- * - use tasklets instead of calling it from the timer-interrupt function
- * - after a special amount of time just turn the machine off (killing init may have failed!)
- * - ....
- */
-
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/string.h>
+#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
@@ -64,9 +82,11 @@
static void deferred_poweroff(void *dummy)
{
- extern int cad_pid; /* kernel/sys.c */
- kill_proc(cad_pid, SIGINT, 1);
- /* machine_power_off(); */
+ extern int cad_pid; /* from kernel/sys.c */
+ if (kill_proc(cad_pid, SIGINT, 1)) {
+ /* just in case killing init process failed */
+ machine_power_off();
+ }
}
/*
@@ -113,6 +133,9 @@ static void process_shutdown(void)
}
+/* main power switch tasklet struct (scheduled from time.c) */
+DECLARE_TASKLET_DISABLED(power_tasklet, NULL, 0);
+
/* soft power switch enabled/disabled */
#ifdef CONFIG_PROC_FS
static int pwrsw_enabled = 1;
@@ -120,23 +143,20 @@ static int pwrsw_enabled = 1;
#define pwrsw_enabled (1)
#endif
-/* soft power switch function ptr */
-void (*check_soft_power)(void);
-
-
/*
* On gecko style machines (e.g. 712/xx and 715/xx)
* the power switch status is stored in Bit 0 ("the highest bit")
* of CPU diagnose register 25.
*
*/
-static void check_soft_power_gecko(void)
+static void gecko_tasklet_func(unsigned long unused)
{
if (!pwrsw_enabled)
return;
if (__getDIAG(25) & 0x80000000) {
/* power switch button not pressed or released again */
+ /* Warning: Some machines do never reset this DIAG flag! */
shutdown_timer = 0;
} else {
process_shutdown();
@@ -150,9 +170,8 @@ static void check_soft_power_gecko(void)
* real I/O location at soft_power_reg.
* Bit 31 ("the lowest bit) is the status of the power switch.
*/
-static unsigned long soft_power_reg;
-static void check_soft_power_polling(void)
+static void polling_tasklet_func(unsigned long soft_power_reg)
{
unsigned long current_status;
@@ -186,6 +205,7 @@ static void powerfail_interrupt(int code
/*
* /proc filesystem support
*/
+
#ifdef CONFIG_SYSCTL
static int power_proc_read(char *page, char **start, off_t off, int count,
int *eof, void *data)
@@ -242,7 +262,7 @@ static struct proc_dir_entry *ent;
static void __init power_create_procfs(void)
{
- if (!check_soft_power)
+ if (!power_tasklet.func)
return;
ent = create_proc_entry(SYSCTL_FILENAME, S_IFREG|S_IRUGO|S_IWUSR, 0);
@@ -266,10 +286,29 @@ static void __exit power_remove_procfs(v
+/* parisc_panic_event() is called by the panic handler.
+ * As soon as a panic occurs, our tasklets above will not be
+ * executed any longer. This function then re-enables the
+ * soft-power switch and allows the user to switch off the system
+ */
+static int parisc_panic_event(struct notifier_block *this,
+ unsigned long event, void *ptr)
+{
+ /* re-enable the soft-power switch */
+ pdc_soft_power_button(0);
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block parisc_panic_block = {
+ notifier_call: parisc_panic_event,
+ priority: INT_MAX,
+};
+
static int __init power_init(void)
{
unsigned long ret;
+ unsigned long soft_power_reg = 0;
#if 0
request_irq( IRQ_FROM_REGION(CPU_IRQ_REGION)+2, &powerfail_interrupt,
@@ -281,38 +320,51 @@ static int __init power_init(void)
if (ret == PDC_OK)
ret = pdc_soft_power_button(1);
if (ret != PDC_OK)
- soft_power_reg = (unsigned long) -1;
+ soft_power_reg = -1UL;
- switch ((long) soft_power_reg) {
+ switch (soft_power_reg) {
case 0: printk(KERN_INFO "Gecko-style soft power switch enabled.\n");
- check_soft_power = check_soft_power_gecko;
+ power_tasklet.func = gecko_tasklet_func;
break;
- case -1: printk(KERN_INFO "Soft power switch support not available.\n");
+ case -1UL: printk(KERN_INFO "Soft power switch support not available.\n");
return -ENODEV;
default: printk(KERN_INFO "Soft power switch enabled, polling @ 0x%08lx.\n",
soft_power_reg);
- check_soft_power = check_soft_power_polling;
+ power_tasklet.data = soft_power_reg;
+ power_tasklet.func = polling_tasklet_func;
}
+ /* Register a call for panic conditions. */
+ notifier_chain_register(&panic_notifier_list, &parisc_panic_block);
+
power_create_procfs();
+ tasklet_enable(&power_tasklet);
return 0;
}
static void __exit power_exit(void)
{
+ if (!power_tasklet.func)
+ return;
+
+ tasklet_disable(&power_tasklet);
+ notifier_chain_unregister(&panic_notifier_list, &parisc_panic_block);
power_remove_procfs();
- check_soft_power = NULL;
+ power_tasklet.func = NULL;
+ pdc_soft_power_button(0);
}
module_init(power_init);
module_exit(power_exit);
+
MODULE_AUTHOR("Helge Deller");
MODULE_DESCRIPTION("Soft power switch driver");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("Dual BSD/GPL");
+
EXPORT_NO_SYMBOLS;
Index: arch/parisc/kernel/time.c
===================================================================
RCS file: /var/cvs/linux/arch/parisc/kernel/time.c,v
retrieving revision 1.23
diff -u -p -r1.23 time.c
--- arch/parisc/kernel/time.c 2002/05/30 16:18:15 1.23
+++ arch/parisc/kernel/time.c 2002/06/26 22:14:59
@@ -116,8 +116,8 @@ void timer_interrupt(int irq, void *dev_
#endif
/* check soft power switch status */
- if (check_soft_power)
- check_soft_power();
+ if (cpu == 0 && !atomic_read(&led_tasklet.count))
+ tasklet_schedule(&power_tasklet);
}
/*** converted from ia64 ***/
Index: include/asm-parisc/irq.h
===================================================================
RCS file: /var/cvs/linux/include/asm-parisc/irq.h,v
retrieving revision 1.21
diff -u -p -r1.21 irq.h
--- include/asm-parisc/irq.h 2001/12/04 02:12:40 1.21
+++ include/asm-parisc/irq.h 2002/06/26 22:14:59
@@ -92,6 +92,6 @@ extern unsigned int txn_alloc_data(int,
extern unsigned long txn_alloc_addr(int);
/* soft power switch support (power.c) */
-extern void (*check_soft_power)(void);
+extern struct tasklet_struct power_tasklet;
#endif /* _ASM_PARISC_IRQ_H */
--Boundary-00=_m7jG9Ny9Z1+7wmF--