aboutsummaryrefslogtreecommitdiff
path: root/drivers/watchdog/wdrtas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/wdrtas.c')
-rw-r--r--drivers/watchdog/wdrtas.c199
1 files changed, 72 insertions, 127 deletions
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c
index 1d64e277567..0240c60d14e 100644
--- a/drivers/watchdog/wdrtas.c
+++ b/drivers/watchdog/wdrtas.c
@@ -26,6 +26,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -35,9 +37,9 @@
#include <linux/reboot.h>
#include <linux/types.h>
#include <linux/watchdog.h>
+#include <linux/uaccess.h>
#include <asm/rtas.h>
-#include <asm/uaccess.h>
#define WDRTAS_MAGIC_CHAR 42
#define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \
@@ -46,17 +48,10 @@
MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
MODULE_DESCRIPTION("RTAS watchdog driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
-MODULE_ALIAS_MISCDEV(TEMP_MINOR);
-
-#ifdef CONFIG_WATCHDOG_NOWAYOUT
-static int wdrtas_nowayout = 1;
-#else
-static int wdrtas_nowayout = 0;
-#endif
+static bool wdrtas_nowayout = WATCHDOG_NOWAYOUT;
static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
-static char wdrtas_expect_close = 0;
+static char wdrtas_expect_close;
static int wdrtas_interval;
@@ -86,8 +81,8 @@ static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
* RTAS function set-indicator (surveillance). The unit of interval is
* seconds.
*/
-static int
-wdrtas_set_interval(int interval)
+
+static int wdrtas_set_interval(int interval)
{
long result;
static int print_msg = 10;
@@ -97,15 +92,17 @@ wdrtas_set_interval(int interval)
result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
WDRTAS_SURVEILLANCE_IND, 0, interval);
- if ( (result < 0) && (print_msg) ) {
- printk(KERN_ERR "wdrtas: setting the watchdog to %i "
- "timeout failed: %li\n", interval, result);
+ if (result < 0 && print_msg) {
+ pr_err("setting the watchdog to %i timeout failed: %li\n",
+ interval, result);
print_msg--;
}
return result;
}
+#define WDRTAS_SP_SPI_LEN 4
+
/**
* wdrtas_get_interval - returns the current watchdog interval
* @fallback_value: value (in seconds) to use, if the RTAS call fails
@@ -116,18 +113,23 @@ wdrtas_set_interval(int interval)
* as reported by the RTAS function ibm,get-system-parameter. The unit
* of the return value is seconds.
*/
-static int
-wdrtas_get_interval(int fallback_value)
+static int wdrtas_get_interval(int fallback_value)
{
long result;
- char value[4];
+ char value[WDRTAS_SP_SPI_LEN];
+ spin_lock(&rtas_data_buf_lock);
+ memset(rtas_data_buf, 0, WDRTAS_SP_SPI_LEN);
result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
- WDRTAS_SP_SPI, (void *)__pa(&value), 4);
- if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
- (result < 0) ) {
- printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
- "timeout (%li). Continuing\n", result);
+ WDRTAS_SP_SPI, __pa(rtas_data_buf),
+ WDRTAS_SP_SPI_LEN);
+
+ memcpy(value, rtas_data_buf, WDRTAS_SP_SPI_LEN);
+ spin_unlock(&rtas_data_buf_lock);
+
+ if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) {
+ pr_warn("could not get sp_spi watchdog timeout (%li). Continuing\n",
+ result);
return fallback_value;
}
@@ -141,8 +143,7 @@ wdrtas_get_interval(int fallback_value)
* wdrtas_timer_start starts the watchdog by calling the RTAS function
* set-interval (surveillance)
*/
-static void
-wdrtas_timer_start(void)
+static void wdrtas_timer_start(void)
{
wdrtas_set_interval(wdrtas_interval);
}
@@ -153,47 +154,19 @@ wdrtas_timer_start(void)
* wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
* set-interval (surveillance)
*/
-static void
-wdrtas_timer_stop(void)
+static void wdrtas_timer_stop(void)
{
wdrtas_set_interval(0);
}
/**
- * wdrtas_log_scanned_event - logs an event we received during keepalive
- *
- * wdrtas_log_scanned_event prints a message to the log buffer dumping
- * the results of the last event-scan call
- */
-static void
-wdrtas_log_scanned_event(void)
-{
- int i;
-
- for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
- printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
- "%02x %02x %02x %02x %02x %02x %02x %02x "
- "%02x %02x %02x %02x %02x %02x %02x %02x\n",
- (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
- wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
- wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
- wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
- wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
- wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
- wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
- wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
- wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
-}
-
-/**
* wdrtas_timer_keepalive - resets watchdog timer to keep system alive
*
* wdrtas_timer_keepalive restarts the watchdog timer by calling the
* RTAS function event-scan and repeats these calls as long as there are
* events available. All events will be dumped.
*/
-static void
-wdrtas_timer_keepalive(void)
+static void wdrtas_timer_keepalive(void)
{
long result;
@@ -203,10 +176,11 @@ wdrtas_timer_keepalive(void)
(void *)__pa(wdrtas_logbuffer),
WDRTAS_LOGBUFFER_LEN);
if (result < 0)
- printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
- result);
+ pr_err("event-scan failed: %li\n", result);
if (result == 0)
- wdrtas_log_scanned_event();
+ print_hex_dump(KERN_INFO, "dumping event, data: ",
+ DUMP_PREFIX_OFFSET, 16, 1,
+ wdrtas_logbuffer, WDRTAS_LOGBUFFER_LEN, false);
} while (result == 0);
}
@@ -218,19 +192,15 @@ wdrtas_timer_keepalive(void)
* wdrtas_get_temperature returns the current temperature in Fahrenheit. It
* uses the RTAS call get-sensor-state, token 3 to do so
*/
-static int
-wdrtas_get_temperature(void)
+static int wdrtas_get_temperature(void)
{
- long result;
+ int result;
int temperature = 0;
- result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
- (void *)__pa(&temperature),
- WDRTAS_THERMAL_SENSOR, 0);
+ result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature);
if (result < 0)
- printk(KERN_WARNING "wdrtas: reading the thermal sensor "
- "faild: %li\n", result);
+ pr_warn("reading the thermal sensor failed: %i\n", result);
else
temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
@@ -243,8 +213,7 @@ wdrtas_get_temperature(void)
* returns a bitmask of defines WDIOF_... as defined in
* include/linux/watchdog.h
*/
-static int
-wdrtas_get_status(void)
+static int wdrtas_get_status(void)
{
return 0; /* TODO */
}
@@ -255,8 +224,7 @@ wdrtas_get_status(void)
* returns a bitmask of defines WDIOF_... as defined in
* include/linux/watchdog.h, indicating why the watchdog rebooted the system
*/
-static int
-wdrtas_get_boot_status(void)
+static int wdrtas_get_boot_status(void)
{
return 0; /* TODO */
}
@@ -276,8 +244,7 @@ wdrtas_get_boot_status(void)
* character 'V'. This character allows the watchdog device to be closed
* properly.
*/
-static ssize_t
-wdrtas_write(struct file *file, const char __user *buf,
+static ssize_t wdrtas_write(struct file *file, const char __user *buf,
size_t len, loff_t *ppos)
{
int i;
@@ -306,7 +273,6 @@ out:
/**
* wdrtas_ioctl - ioctl function for the watchdog device
- * @inode: inode structure
* @file: file structure
* @cmd: command for ioctl
* @arg: argument pointer
@@ -315,16 +281,16 @@ out:
*
* wdrtas_ioctl implements the watchdog API ioctls
*/
-static int
-wdrtas_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+
+static long wdrtas_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
{
int __user *argp = (void __user *)arg;
int i;
- static struct watchdog_info wdinfo = {
+ static const struct watchdog_info wdinfo = {
.options = WDRTAS_SUPPORTED_MASK,
.firmware_version = 0,
- .identity = "wdrtas"
+ .identity = "wdrtas",
};
switch (cmd) {
@@ -357,9 +323,9 @@ wdrtas_ioctl(struct inode *inode, struct file *file,
wdrtas_timer_keepalive();
wdrtas_timer_start();
}
+ /* not implemented. Done by H8
if (i & WDIOS_TEMPPANIC) {
- /* not implemented. Done by H8 */
- }
+ } */
return 0;
case WDIOC_KEEPALIVE:
@@ -399,8 +365,7 @@ wdrtas_ioctl(struct inode *inode, struct file *file,
*
* function called when watchdog device is opened
*/
-static int
-wdrtas_open(struct inode *inode, struct file *file)
+static int wdrtas_open(struct inode *inode, struct file *file)
{
/* only open once */
if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
@@ -423,15 +388,13 @@ wdrtas_open(struct inode *inode, struct file *file)
*
* close function. Always succeeds
*/
-static int
-wdrtas_close(struct inode *inode, struct file *file)
+static int wdrtas_close(struct inode *inode, struct file *file)
{
/* only stop watchdog, if this was announced using 'V' before */
if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
wdrtas_timer_stop();
else {
- printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
- "not stopped.\n");
+ pr_warn("got unexpected close. Watchdog not stopped.\n");
wdrtas_timer_keepalive();
}
@@ -453,8 +416,7 @@ wdrtas_close(struct inode *inode, struct file *file)
* wdrtas_temp_read gives the temperature to the users by copying this
* value as one byte into the user space buffer. The unit is Fahrenheit...
*/
-static ssize_t
-wdrtas_temp_read(struct file *file, char __user *buf,
+static ssize_t wdrtas_temp_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
int temperature = 0;
@@ -478,8 +440,7 @@ wdrtas_temp_read(struct file *file, char __user *buf,
*
* function called when temperature device is opened
*/
-static int
-wdrtas_temp_open(struct inode *inode, struct file *file)
+static int wdrtas_temp_open(struct inode *inode, struct file *file)
{
return nonseekable_open(inode, file);
}
@@ -493,8 +454,7 @@ wdrtas_temp_open(struct inode *inode, struct file *file)
*
* close function. Always succeeds
*/
-static int
-wdrtas_temp_close(struct inode *inode, struct file *file)
+static int wdrtas_temp_close(struct inode *inode, struct file *file)
{
return 0;
}
@@ -509,10 +469,10 @@ wdrtas_temp_close(struct inode *inode, struct file *file)
*
* wdrtas_reboot stops the watchdog in case of a reboot
*/
-static int
-wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
+static int wdrtas_reboot(struct notifier_block *this,
+ unsigned long code, void *ptr)
{
- if ( (code==SYS_DOWN) || (code==SYS_HALT) )
+ if (code == SYS_DOWN || code == SYS_HALT)
wdrtas_timer_stop();
return NOTIFY_DONE;
@@ -524,7 +484,7 @@ static const struct file_operations wdrtas_fops = {
.owner = THIS_MODULE,
.llseek = no_llseek,
.write = wdrtas_write,
- .ioctl = wdrtas_ioctl,
+ .unlocked_ioctl = wdrtas_ioctl,
.open = wdrtas_open,
.release = wdrtas_close,
};
@@ -556,41 +516,34 @@ static struct notifier_block wdrtas_notifier = {
/**
* wdrtas_get_tokens - reads in RTAS tokens
*
- * returns 0 on succes, <0 on failure
+ * returns 0 on success, <0 on failure
*
* wdrtas_get_tokens reads in the tokens for the RTAS calls used in
* this watchdog driver. It tolerates, if "get-sensor-state" and
* "ibm,get-system-parameter" are not available.
*/
-static int
-wdrtas_get_tokens(void)
+static int wdrtas_get_tokens(void)
{
wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
- printk(KERN_WARNING "wdrtas: couldn't get token for "
- "get-sensor-state. Trying to continue without "
- "temperature support.\n");
+ pr_warn("couldn't get token for get-sensor-state. Trying to continue without temperature support.\n");
}
wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
- printk(KERN_WARNING "wdrtas: couldn't get token for "
- "ibm,get-system-parameter. Trying to continue with "
- "a default timeout value of %i seconds.\n",
- WDRTAS_DEFAULT_INTERVAL);
+ pr_warn("couldn't get token for ibm,get-system-parameter. Trying to continue with a default timeout value of %i seconds.\n",
+ WDRTAS_DEFAULT_INTERVAL);
}
wdrtas_token_set_indicator = rtas_token("set-indicator");
if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
- printk(KERN_ERR "wdrtas: couldn't get token for "
- "set-indicator. Terminating watchdog code.\n");
+ pr_err("couldn't get token for set-indicator. Terminating watchdog code.\n");
return -EIO;
}
wdrtas_token_event_scan = rtas_token("event-scan");
if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
- printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
- "Terminating watchdog code.\n");
+ pr_err("couldn't get token for event-scan. Terminating watchdog code.\n");
return -EIO;
}
@@ -603,8 +556,7 @@ wdrtas_get_tokens(void)
* wdrtas_register_devs unregisters the watchdog and temperature watchdog
* misc devs
*/
-static void
-wdrtas_unregister_devs(void)
+static void wdrtas_unregister_devs(void)
{
misc_deregister(&wdrtas_miscdev);
if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
@@ -614,29 +566,25 @@ wdrtas_unregister_devs(void)
/**
* wdrtas_register_devs - registers the misc dev handlers
*
- * returns 0 on succes, <0 on failure
+ * returns 0 on success, <0 on failure
*
* wdrtas_register_devs registers the watchdog and temperature watchdog
* misc devs
*/
-static int
-wdrtas_register_devs(void)
+static int wdrtas_register_devs(void)
{
int result;
result = misc_register(&wdrtas_miscdev);
if (result) {
- printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
- "device. Terminating watchdog code.\n");
+ pr_err("couldn't register watchdog misc device. Terminating watchdog code.\n");
return result;
}
if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
result = misc_register(&wdrtas_tempdev);
if (result) {
- printk(KERN_WARNING "wdrtas: couldn't register "
- "watchdog temperature misc device. Continuing "
- "without temperature support.\n");
+ pr_warn("couldn't register watchdog temperature misc device. Continuing without temperature support.\n");
wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
}
}
@@ -647,12 +595,11 @@ wdrtas_register_devs(void)
/**
* wdrtas_init - init function of the watchdog driver
*
- * returns 0 on succes, <0 on failure
+ * returns 0 on success, <0 on failure
*
* registers the file handlers and the reboot notifier
*/
-static int __init
-wdrtas_init(void)
+static int __init wdrtas_init(void)
{
if (wdrtas_get_tokens())
return -ENODEV;
@@ -661,8 +608,7 @@ wdrtas_init(void)
return -ENODEV;
if (register_reboot_notifier(&wdrtas_notifier)) {
- printk(KERN_ERR "wdrtas: could not register reboot notifier. "
- "Terminating watchdog code.\n");
+ pr_err("could not register reboot notifier. Terminating watchdog code.\n");
wdrtas_unregister_devs();
return -ENODEV;
}
@@ -680,8 +626,7 @@ wdrtas_init(void)
*
* unregisters the file handlers and the reboot notifier
*/
-static void __exit
-wdrtas_exit(void)
+static void __exit wdrtas_exit(void)
{
if (!wdrtas_nowayout)
wdrtas_timer_stop();