Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
47c44594
Commit
47c44594
authored
Aug 13, 2003
by
Linus Torvalds
Browse files
Options
Browse Files
Download
Plain Diff
Merge
http://linux-watchdog.bkbits.net/linux-2.5-watchdog
into home.osdl.org:/home/torvalds/v2.5/linux
parents
e5dbafd4
e26d4f47
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
258 additions
and
148 deletions
+258
-148
drivers/char/watchdog/alim7101_wdt.c
drivers/char/watchdog/alim7101_wdt.c
+112
-60
drivers/char/watchdog/sc520_wdt.c
drivers/char/watchdog/sc520_wdt.c
+146
-88
No files found.
drivers/char/watchdog/alim7101_wdt.c
View file @
47c44594
/*
* ALi M7101 PMU Computer Watchdog Timer driver
for Linux 2.4.x
* ALi M7101 PMU Computer Watchdog Timer driver
*
* Based on w83877f_wdt.c by Scott Jennings <
management
@oro.net>
* Based on w83877f_wdt.c by Scott Jennings <
linuxdrivers
@oro.net>
* and the Cobalt kernel WDT timer driver by Tim Hockin
* <thockin@cobaltnet.com>
*
* (c)2002 Steve Hill <steve@navaho.co.uk>
*
* Theory of operation:
* A Watchdog Timer (WDT) is a hardware circuit that can
* reset the computer system in case of a software fault.
* You probably knew that already.
*
* Usually a userspace daemon will notify the kernel WDT driver
* via the /proc/watchdog special device file that userspace is
* still alive, at regular intervals. When such a notification
* occurs, the driver will usually tell the hardware watchdog
* that everything is in order, and that the watchdog should wait
* for yet another little while to reset the system.
* If userspace fails (RAM error, kernel bug, whatever), the
* notifications cease to occur, and the hardware watchdog will
* reset the system (causing a reboot) after the timeout occurs.
*
* This WDT driver is different from most other Linux WDT
* drivers in that the driver will ping the watchdog by itself,
* because this particular WDT has a very short timeout (1.6
...
...
@@ -30,6 +15,7 @@
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/timer.h>
#include <linux/miscdevice.h>
...
...
@@ -38,7 +24,6 @@
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/pci.h>
#include <asm/io.h>
...
...
@@ -46,6 +31,7 @@
#include <asm/system.h>
#define OUR_NAME "alim7101_wdt"
#define PFX OUR_NAME ": "
#define WDT_ENABLE 0x9C
#define WDT_DISABLE 0x8C
...
...
@@ -65,13 +51,16 @@
* char to /dev/watchdog every 30 seconds.
*/
#define WDT_HEARTBEAT (HZ * 30)
#define WATCHDOG_TIMEOUT 30
/* 30 sec default timeout */
static
int
timeout
=
WATCHDOG_TIMEOUT
;
/* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
module_param
(
timeout
,
int
,
0
);
MODULE_PARM_DESC
(
timeout
,
"Watchdog timeout in seconds. (1<=timeout<=3600, default="
__MODULE_STRING
(
WATCHDOG_TIMEOUT
)
")"
);
static
void
wdt_timer_ping
(
unsigned
long
);
static
struct
timer_list
timer
;
static
unsigned
long
next_heartbeat
;
static
unsigned
long
wdt_is_open
;
static
int
wdt_expect_close
;
static
char
wdt_expect_close
;
static
struct
pci_dev
*
alim7101_pmu
;
#ifdef CONFIG_WATCHDOG_NOWAYOUT
...
...
@@ -101,7 +90,7 @@ static void wdt_timer_ping(unsigned long data)
pci_write_config_byte
(
alim7101_pmu
,
ALI_7101_WDT
,
(
tmp
&
~
ALI_WDT_ARM
));
pci_write_config_byte
(
alim7101_pmu
,
ALI_7101_WDT
,
(
tmp
|
ALI_WDT_ARM
));
}
else
{
printk
(
KERN_
INFO
OUR_NAME
":
Heartbeat lost! Will not ping the watchdog
\n
"
);
printk
(
KERN_
WARNING
PFX
"
Heartbeat lost! Will not ping the watchdog
\n
"
);
}
/* Re-set the timer interval */
timer
.
expires
=
jiffies
+
WDT_INTERVAL
;
...
...
@@ -125,7 +114,7 @@ static void wdt_change(int writeval)
static
void
wdt_startup
(
void
)
{
next_heartbeat
=
jiffies
+
WDT_HEARTBEAT
;
next_heartbeat
=
jiffies
+
(
timeout
*
HZ
)
;
/* We must enable before we kick off the timer in case the timer
occurs as we ping it */
...
...
@@ -137,7 +126,7 @@ static void wdt_startup(void)
add_timer
(
&
timer
);
printk
(
KERN_INFO
OUR_NAME
": Watchdog timer is now enabled.
\n
"
);
printk
(
KERN_INFO
PFX
"Watchdog timer is now enabled.
\n
"
);
}
static
void
wdt_turnoff
(
void
)
...
...
@@ -145,7 +134,13 @@ static void wdt_turnoff(void)
/* Stop the timer */
del_timer_sync
(
&
timer
);
wdt_change
(
WDT_DISABLE
);
printk
(
KERN_INFO
OUR_NAME
": Watchdog timer is now disabled...
\n
"
);
printk
(
KERN_INFO
PFX
"Watchdog timer is now disabled...
\n
"
);
}
static
void
wdt_keepalive
(
void
)
{
/* user land ping */
next_heartbeat
=
jiffies
+
(
timeout
*
HZ
);
}
/*
...
...
@@ -158,7 +153,7 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
/* See if we got the magic character */
/* See if we got the magic character
'V' and reload the timer
*/
if
(
count
)
{
if
(
!
nowayout
)
{
size_t
ofs
;
...
...
@@ -173,14 +168,13 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof
if
(
get_user
(
c
,
buf
+
ofs
))
return
-
EFAULT
;
if
(
c
==
'V'
)
wdt_expect_close
=
1
;
wdt_expect_close
=
42
;
}
}
/* someone wrote to us, we should restart timer */
next_heartbeat
=
jiffies
+
WDT_HEARTBEAT
;
return
1
;
};
return
0
;
wdt_keepalive
();
}
return
count
;
}
static
int
fop_open
(
struct
inode
*
inode
,
struct
file
*
file
)
...
...
@@ -195,12 +189,14 @@ static int fop_open(struct inode * inode, struct file * file)
static
int
fop_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
wdt_expect_close
)
if
(
wdt_expect_close
==
42
)
wdt_turnoff
();
else
printk
(
KERN_INFO
OUR_NAME
": device file closed unexpectedly. Will not stop the WDT!
\n
"
);
else
{
/* wim: shouldn't there be a: del_timer(&timer); */
printk
(
KERN_CRIT
PFX
"device file closed unexpectedly. Will not stop the WDT!
\n
"
);
}
clear_bit
(
0
,
&
wdt_is_open
);
wdt_expect_close
=
0
;
return
0
;
}
...
...
@@ -208,20 +204,58 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, u
{
static
struct
watchdog_info
ident
=
{
.
options
=
WDIOF_MAGICCLOSE
,
.
options
=
WDIOF_
KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_
MAGICCLOSE
,
.
firmware_version
=
1
,
.
identity
=
"ALiM7101"
.
identity
=
"ALiM7101"
,
};
switch
(
cmd
)
{
case
WDIOC_GETSUPPORT
:
return
copy_to_user
((
struct
watchdog_info
*
)
arg
,
&
ident
,
sizeof
(
ident
))
?-
EFAULT
:
0
;
case
WDIOC_GETSTATUS
:
case
WDIOC_GETBOOTSTATUS
:
return
put_user
(
0
,
(
int
*
)
arg
);
case
WDIOC_KEEPALIVE
:
next_heartbeat
=
jiffies
+
WDT_HEARTBEAT
;
wdt_keepalive
()
;
return
0
;
case
WDIOC_SETOPTIONS
:
{
int
new_options
,
retval
=
-
EINVAL
;
if
(
get_user
(
new_options
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
new_options
&
WDIOS_DISABLECARD
)
{
wdt_turnoff
();
retval
=
0
;
}
if
(
new_options
&
WDIOS_ENABLECARD
)
{
wdt_startup
();
retval
=
0
;
}
return
retval
;
}
case
WDIOC_SETTIMEOUT
:
{
int
new_timeout
;
if
(
get_user
(
new_timeout
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
new_timeout
<
1
||
new_timeout
>
3600
)
/* arbitrary upper limit */
return
-
EINVAL
;
timeout
=
new_timeout
;
wdt_keepalive
();
/* Fall through */
}
case
WDIOC_GETTIMEOUT
:
return
put_user
(
timeout
,
(
int
*
)
arg
);
default:
return
-
ENO
TTY
;
return
-
ENO
IOCTLCMD
;
}
}
...
...
@@ -231,13 +265,13 @@ static struct file_operations wdt_fops = {
.
write
=
fop_write
,
.
open
=
fop_open
,
.
release
=
fop_close
,
.
ioctl
=
fop_ioctl
.
ioctl
=
fop_ioctl
,
};
static
struct
miscdevice
wdt_miscdev
=
{
.
minor
=
WATCHDOG_MINOR
,
.
name
=
"watchdog"
,
.
fops
=&
wdt_fops
.
fops
=&
wdt_fops
,
};
/*
...
...
@@ -256,7 +290,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void
* reboot with no heartbeat
*/
wdt_change
(
WDT_ENABLE
);
printk
(
KERN_INFO
OUR_NAME
":
Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.
\n
"
);
printk
(
KERN_INFO
PFX
"
Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.
\n
"
);
}
return
NOTIFY_DONE
;
}
...
...
@@ -270,7 +304,7 @@ static struct notifier_block wdt_notifier=
{
.
notifier_call
=
wdt_notify_sys
,
.
next
=
0
,
.
priority
=
0
.
priority
=
0
,
};
static
void
__exit
alim7101_wdt_unload
(
void
)
...
...
@@ -287,10 +321,10 @@ static int __init alim7101_wdt_init(void)
struct
pci_dev
*
ali1543_south
;
char
tmp
;
printk
(
KERN_INFO
OUR_NAME
":
Steve Hill <steve@navaho.co.uk>.
\n
"
);
printk
(
KERN_INFO
PFX
"
Steve Hill <steve@navaho.co.uk>.
\n
"
);
alim7101_pmu
=
pci_find_device
(
PCI_VENDOR_ID_AL
,
PCI_DEVICE_ID_AL_M7101
,
NULL
);
if
(
!
alim7101_pmu
)
{
printk
(
KERN_INFO
OUR_NAME
":
ALi M7101 PMU not present - WDT not set
\n
"
);
printk
(
KERN_INFO
PFX
"
ALi M7101 PMU not present - WDT not set
\n
"
);
return
-
EBUSY
;
}
...
...
@@ -299,35 +333,53 @@ static int __init alim7101_wdt_init(void)
ali1543_south
=
pci_find_device
(
PCI_VENDOR_ID_AL
,
PCI_DEVICE_ID_AL_M1533
,
NULL
);
if
(
!
ali1543_south
)
{
printk
(
KERN_INFO
OUR_NAME
":
ALi 1543 South-Bridge not present - WDT not set
\n
"
);
printk
(
KERN_INFO
PFX
"
ALi 1543 South-Bridge not present - WDT not set
\n
"
);
return
-
EBUSY
;
}
pci_read_config_byte
(
ali1543_south
,
0x5e
,
&
tmp
);
if
((
tmp
&
0x1e
)
!=
0x12
)
{
printk
(
KERN_INFO
OUR_NAME
":
ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set
\n
"
);
printk
(
KERN_INFO
PFX
"
ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set
\n
"
);
return
-
EBUSY
;
}
if
(
timeout
<
1
||
timeout
>
3600
)
/* arbitrary upper limit */
{
timeout
=
WATCHDOG_TIMEOUT
;
printk
(
KERN_INFO
PFX
"timeout value must be 1<=x<=3600, using %d
\n
"
,
timeout
);
}
init_timer
(
&
timer
);
timer
.
function
=
wdt_timer_ping
;
timer
.
data
=
1
;
rc
=
misc_register
(
&
wdt_miscdev
);
if
(
rc
)
return
rc
;
if
(
rc
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
wdt_miscdev
.
minor
,
rc
);
goto
err_out
;
}
rc
=
register_reboot_notifier
(
&
wdt_notifier
);
if
(
rc
)
{
misc_deregister
(
&
wdt_miscdev
);
return
rc
;
printk
(
KERN_ERR
PFX
"cannot register reboot notifier (err=%d)
\n
"
,
rc
);
goto
err_out_miscdev
;
}
printk
(
KERN_INFO
OUR_NAME
": WDT driver for ALi M7101 initialised.
\n
"
);
printk
(
KERN_INFO
PFX
"WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)
\n
"
,
timeout
,
nowayout
);
return
0
;
err_out_miscdev:
misc_deregister
(
&
wdt_miscdev
);
err_out:
return
rc
;
}
module_init
(
alim7101_wdt_init
);
module_exit
(
alim7101_wdt_unload
);
MODULE_AUTHOR
(
"Steve Hill"
);
MODULE_DESCRIPTION
(
"ALi M7101 PMU Computer Watchdog Timer driver"
);
MODULE_LICENSE
(
"GPL"
);
drivers/char/watchdog/sc520_wdt.c
View file @
47c44594
/*
* AMD Elan SC520 processor Watchdog Timer driver
for Linux 2.4.x
* AMD Elan SC520 processor Watchdog Timer driver
*
* Based on acquirewdt.c by Alan Cox,
* and sbc60xxwdt.c by Jakob Oestergaard <jakob@
ostenfeld.dk
>
* and sbc60xxwdt.c by Jakob Oestergaard <jakob@
unthought.net
>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
...
...
@@ -24,20 +24,21 @@
* - Used ioremap/writew/readw
* - Added NOWAYOUT support
*
* Theory of operation:
* A Watchdog Timer (WDT) is a hardware circuit that can
* reset the computer system in case of a software fault.
* You probably knew that already.
*
* Usually a userspace daemon will notify the kernel WDT driver
* via the /proc/watchdog special device file that userspace is
* still alive, at regular intervals. When such a notification
* occurs, the driver will usually tell the hardware watchdog
* that everything is in order, and that the watchdog should wait
* for yet another little while to reset the system.
* If userspace fails (RAM error, kernel bug, whatever), the
* notifications cease to occur, and the hardware watchdog will
* reset the system (causing a reboot) after the timeout occurs.
* 4/12 - 2002 Changes by Rob Radez <rob@osinvestor.com>
* - Change comments
* - Eliminate fop_llseek
* - Change CONFIG_WATCHDOG_NOWAYOUT semantics
* - Add KERN_* tags to printks
* - fix possible wdt_is_open race
* - Report proper capabilities in watchdog_info
* - Add WDIOC_{GETSTATUS, GETBOOTSTATUS, SETTIMEOUT,
* GETTIMEOUT, SETOPTIONS} ioctls
* 09/8 - 2003 Changes by Wim Van Sebroeck <wim@iguana.be>
* - cleanup of trailing spaces
* - added extra printk's for startup problems
* - use module_param
* - made timeout (the emulated heartbeat) a module_param
* - made the keepalive ping an internal subroutine
*
* This WDT driver is different from most other Linux WDT
* drivers in that the driver will ping the watchdog by itself,
...
...
@@ -77,7 +78,10 @@
* char to /dev/watchdog every 30 seconds.
*/
#define WDT_HEARTBEAT (HZ * 30)
#define WATCHDOG_TIMEOUT 30
/* 30 sec default timeout */
static
int
timeout
=
WATCHDOG_TIMEOUT
;
/* in seconds, will be multiplied by HZ to get seconds to wait for a ping */
module_param
(
timeout
,
int
,
0
);
MODULE_PARM_DESC
(
timeout
,
"Watchdog timeout in seconds. (1<=timeout<=3600, default="
__MODULE_STRING
(
WATCHDOG_TIMEOUT
)
")"
);
/*
* AMD Elan SC520 timeout value is 492us times a power of 2 (0-7)
...
...
@@ -95,6 +99,7 @@
#define WDT_WRST_ENB 0x4000
/* [14] Watchdog Timer Reset Enable */
#define OUR_NAME "sc520_wdt"
#define PFX OUR_NAME ": "
#define WRT_DOG(data) *wdtmrctl=data
...
...
@@ -104,7 +109,8 @@ static void wdt_timer_ping(unsigned long);
static
struct
timer_list
timer
;
static
unsigned
long
next_heartbeat
;
static
unsigned
long
wdt_is_open
;
static
int
wdt_expect_close
;
static
char
wdt_expect_close
;
static
spinlock_t
wdt_spinlock
;
#ifdef CONFIG_WATCHDOG_NOWAYOUT
static
int
nowayout
=
1
;
...
...
@@ -115,7 +121,6 @@ static int nowayout = 0;
module_param
(
nowayout
,
int
,
0
);
MODULE_PARM_DESC
(
nowayout
,
"Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"
);
static
spinlock_t
wdt_spinlock
;
/*
* Whack the dog
*/
...
...
@@ -137,7 +142,7 @@ static void wdt_timer_ping(unsigned long data)
timer
.
expires
=
jiffies
+
WDT_INTERVAL
;
add_timer
(
&
timer
);
}
else
{
printk
(
OUR_NAME
":
Heartbeat lost! Will not ping the watchdog
\n
"
);
printk
(
KERN_WARNING
PFX
"
Heartbeat lost! Will not ping the watchdog
\n
"
);
}
}
...
...
@@ -165,14 +170,14 @@ static void wdt_config(int writeval)
static
void
wdt_startup
(
void
)
{
next_heartbeat
=
jiffies
+
WDT_HEARTBEAT
;
next_heartbeat
=
jiffies
+
(
timeout
*
HZ
)
;
/* Start the timer */
timer
.
expires
=
jiffies
+
WDT_INTERVAL
;
add_timer
(
&
timer
);
wdt_config
(
WDT_ENB
|
WDT_WRST_ENB
|
TIMEOUT_EXPONENT
);
printk
(
OUR_NAME
": Watchdog timer is now enabled.
\n
"
);
printk
(
KERN_INFO
PFX
"Watchdog timer is now enabled.
\n
"
);
}
static
void
wdt_turnoff
(
void
)
...
...
@@ -181,10 +186,15 @@ static void wdt_turnoff(void)
/* Stop the timer */
del_timer
(
&
timer
);
wdt_config
(
0
);
printk
(
OUR_NAME
":
Watchdog timer is now disabled...
\n
"
);
printk
(
KERN_INFO
PFX
"
Watchdog timer is now disabled...
\n
"
);
}
}
static
void
wdt_keepalive
(
void
)
{
/* user land ping */
next_heartbeat
=
jiffies
+
(
timeout
*
HZ
);
}
/*
* /dev/watchdog handling
...
...
@@ -196,8 +206,10 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof
if
(
ppos
!=
&
file
->
f_pos
)
return
-
ESPIPE
;
/* See if we got the magic character */
/* See if we got the magic character
'V' and reload the timer
*/
if
(
count
)
{
if
(
!
nowayout
)
{
size_t
ofs
;
...
...
@@ -211,47 +223,39 @@ static ssize_t fop_write(struct file * file, const char * buf, size_t count, lof
if
(
get_user
(
c
,
buf
+
ofs
))
return
-
EFAULT
;
if
(
c
==
'V'
)
wdt_expect_close
=
1
;
wdt_expect_close
=
42
;
}
}
/* Well, anyhow someone wrote to us, we should return that favour */
next_heartbeat
=
jiffies
+
WDT_HEARTBEAT
;
return
1
;
wdt_keepalive
();
}
return
0
;
return
count
;
}
static
int
fop_open
(
struct
inode
*
inode
,
struct
file
*
file
)
{
switch
(
minor
(
inode
->
i_rdev
))
{
case
WATCHDOG_MINOR
:
/* Just in case we're already talking to someone... */
if
(
test_and_set_bit
(
0
,
&
wdt_is_open
))
return
-
EBUSY
;
/* Good, fire up the show */
wdt_startup
();
if
(
nowayout
)
__module_get
(
THIS_MODULE
);
/* Good, fire up the show */
wdt_startup
();
return
0
;
default:
return
-
ENODEV
;
}
}
static
int
fop_close
(
struct
inode
*
inode
,
struct
file
*
file
)
{
if
(
minor
(
inode
->
i_rdev
)
==
WATCHDOG_MINOR
)
{
if
(
wdt_expect_close
)
if
(
wdt_expect_close
==
42
)
wdt_turnoff
();
else
{
del_timer
(
&
timer
);
printk
(
OUR_NAME
": device file closed unexpectedly. Will not stop the WDT!
\n
"
);
}
printk
(
KERN_CRIT
PFX
"device file closed unexpectedly. Will not stop the WDT!
\n
"
);
}
clear_bit
(
0
,
&
wdt_is_open
);
wdt_expect_close
=
0
;
return
0
;
}
...
...
@@ -260,9 +264,9 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
{
static
struct
watchdog_info
ident
=
{
.
options
=
WDIOF_MAGICCLOSE
,
.
options
=
WDIOF_
KEEPALIVEPING
|
WDIOF_SETTIMEOUT
|
WDIOF_
MAGICCLOSE
,
.
firmware_version
=
1
,
.
identity
=
"SC520"
.
identity
=
"SC520"
,
};
switch
(
cmd
)
...
...
@@ -271,9 +275,47 @@ static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
return
-
ENOIOCTLCMD
;
case
WDIOC_GETSUPPORT
:
return
copy_to_user
((
struct
watchdog_info
*
)
arg
,
&
ident
,
sizeof
(
ident
))
?-
EFAULT
:
0
;
case
WDIOC_GETSTATUS
:
case
WDIOC_GETBOOTSTATUS
:
return
put_user
(
0
,
(
int
*
)
arg
);
case
WDIOC_KEEPALIVE
:
next_heartbeat
=
jiffies
+
WDT_HEARTBEAT
;
wdt_keepalive
()
;
return
0
;
case
WDIOC_SETOPTIONS
:
{
int
new_options
,
retval
=
-
EINVAL
;
if
(
get_user
(
new_options
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
new_options
&
WDIOS_DISABLECARD
)
{
wdt_turnoff
();
retval
=
0
;
}
if
(
new_options
&
WDIOS_ENABLECARD
)
{
wdt_startup
();
retval
=
0
;
}
return
retval
;
}
case
WDIOC_SETTIMEOUT
:
{
int
new_timeout
;
if
(
get_user
(
new_timeout
,
(
int
*
)
arg
))
return
-
EFAULT
;
if
(
new_timeout
<
1
||
new_timeout
>
3600
)
/* arbitrary upper limit */
return
-
EINVAL
;
timeout
=
new_timeout
;
wdt_keepalive
();
/* Fall through */
}
case
WDIOC_GETTIMEOUT
:
return
put_user
(
timeout
,
(
int
*
)
arg
);
}
}
...
...
@@ -283,13 +325,13 @@ static struct file_operations wdt_fops = {
.
write
=
fop_write
,
.
open
=
fop_open
,
.
release
=
fop_close
,
.
ioctl
=
fop_ioctl
.
ioctl
=
fop_ioctl
,
};
static
struct
miscdevice
wdt_miscdev
=
{
.
minor
=
WATCHDOG_MINOR
,
.
name
=
"watchdog"
,
.
fops
=
&
wdt_fops
.
fops
=
&
wdt_fops
,
};
/*
...
...
@@ -313,7 +355,7 @@ static struct notifier_block wdt_notifier=
{
.
notifier_call
=
wdt_notify_sys
,
.
next
=
NULL
,
.
priority
=
0
.
priority
=
0
,
};
static
void
__exit
sc520_wdt_unload
(
void
)
...
...
@@ -333,27 +375,42 @@ static int __init sc520_wdt_init(void)
spin_lock_init
(
&
wdt_spinlock
);
if
(
timeout
<
1
||
timeout
>
3600
)
/* arbitrary upper limit */
{
timeout
=
WATCHDOG_TIMEOUT
;
printk
(
KERN_INFO
PFX
"timeout value must be 1<=x<=3600, using %d
\n
"
,
timeout
);
}
init_timer
(
&
timer
);
timer
.
function
=
wdt_timer_ping
;
timer
.
data
=
0
;
rc
=
misc_register
(
&
wdt_miscdev
);
if
(
rc
)
{
printk
(
KERN_ERR
PFX
"cannot register miscdev on minor=%d (err=%d)
\n
"
,
wdt_miscdev
.
minor
,
rc
);
goto
err_out_region2
;
}
rc
=
register_reboot_notifier
(
&
wdt_notifier
);
if
(
rc
)
{
printk
(
KERN_ERR
PFX
"cannot register reboot notifier (err=%d)
\n
"
,
rc
);
goto
err_out_miscdev
;
}
/* get the Base Address Register */
cbar
=
inl_p
(
0xfffc
);
printk
(
OUR_NAME
":
CBAR: 0x%08lx
\n
"
,
cbar
);
printk
(
KERN_INFO
PFX
"
CBAR: 0x%08lx
\n
"
,
cbar
);
/* check if MMCR aliasing bit is set */
if
(
cbar
&
0x80000000
)
{
printk
(
OUR_NAME
":
MMCR Aliasing enabled.
\n
"
);
printk
(
KERN_INFO
PFX
"
MMCR Aliasing enabled.
\n
"
);
wdtmrctl
=
(
__u16
*
)(
cbar
&
0x3fffffff
);
}
else
{
printk
(
OUR_NAME
"!!! WARNING !!!
\n
"
printk
(
KERN_INFO
PFX
"!!! WARNING !!!
\n
"
"
\t
MMCR Aliasing found NOT enabled!
\n
"
"
\t
Using default value of: %p
\n
"
"
\t
This has not been tested!
\n
"
...
...
@@ -366,7 +423,8 @@ static int __init sc520_wdt_init(void)
wdtmrctl
=
(
__u16
*
)((
char
*
)
wdtmrctl
+
OFFS_WDTMRCTL
);
wdtmrctl
=
ioremap
((
unsigned
long
)
wdtmrctl
,
2
);
printk
(
KERN_INFO
OUR_NAME
": WDT driver for SC520 initialised.
\n
"
);
printk
(
KERN_INFO
PFX
"WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)
\n
"
,
timeout
,
nowayout
);
return
0
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment