aboutsummaryrefslogtreecommitdiff
path: root/drivers/watchdog/ibmasr.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog/ibmasr.c')
-rw-r--r--drivers/watchdog/ibmasr.c166
1 files changed, 92 insertions, 74 deletions
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c
index 94155f6136c..366b0474f27 100644
--- a/drivers/watchdog/ibmasr.c
+++ b/drivers/watchdog/ibmasr.c
@@ -10,18 +10,18 @@
* of the GNU Public License, incorporated herein by reference.
*/
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
#include <linux/fs.h>
#include <linux/kernel.h>
-#include <linux/slab.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/timer.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/dmi.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
enum {
@@ -33,8 +33,6 @@ enum {
ASMTYPE_SPRUCE,
};
-#define PFX "ibmasr: "
-
#define TOPAZ_ASR_REG_OFFSET 4
#define TOPAZ_ASR_TOGGLE 0x40
#define TOPAZ_ASR_DISABLE 0x80
@@ -62,7 +60,7 @@ enum {
#define SPRUCE_ASR_TOGGLE_MASK 0x02 /* bit 0: 0, then 1, then 0 */
-static int nowayout = WATCHDOG_NOWAYOUT;
+static bool nowayout = WATCHDOG_NOWAYOUT;
static unsigned long asr_is_open;
static char asr_expect_close;
@@ -70,10 +68,13 @@ static char asr_expect_close;
static unsigned int asr_type, asr_base, asr_length;
static unsigned int asr_read_addr, asr_write_addr;
static unsigned char asr_toggle_mask, asr_disable_mask;
+static DEFINE_SPINLOCK(asr_lock);
-static void asr_toggle(void)
+static void __asr_toggle(void)
{
- unsigned char reg = inb(asr_read_addr);
+ unsigned char reg;
+
+ reg = inb(asr_read_addr);
outb(reg & ~asr_toggle_mask, asr_write_addr);
reg = inb(asr_read_addr);
@@ -85,10 +86,18 @@ static void asr_toggle(void)
reg = inb(asr_read_addr);
}
+static void asr_toggle(void)
+{
+ spin_lock(&asr_lock);
+ __asr_toggle();
+ spin_unlock(&asr_lock);
+}
+
static void asr_enable(void)
{
unsigned char reg;
+ spin_lock(&asr_lock);
if (asr_type == ASMTYPE_TOPAZ) {
/* asr_write_addr == asr_read_addr */
reg = inb(asr_read_addr);
@@ -99,17 +108,21 @@ static void asr_enable(void)
* First make sure the hardware timer is reset by toggling
* ASR hardware timer line.
*/
- asr_toggle();
+ __asr_toggle();
reg = inb(asr_read_addr);
outb(reg & ~asr_disable_mask, asr_write_addr);
}
reg = inb(asr_read_addr);
+ spin_unlock(&asr_lock);
}
static void asr_disable(void)
{
- unsigned char reg = inb(asr_read_addr);
+ unsigned char reg;
+
+ spin_lock(&asr_lock);
+ reg = inb(asr_read_addr);
if (asr_type == ASMTYPE_TOPAZ)
/* asr_write_addr == asr_read_addr */
@@ -122,6 +135,7 @@ static void asr_disable(void)
outb(reg | asr_disable_mask, asr_write_addr);
}
reg = inb(asr_read_addr);
+ spin_unlock(&asr_lock);
}
static int __init asr_get_base_address(void)
@@ -133,7 +147,8 @@ static int __init asr_get_base_address(void)
switch (asr_type) {
case ASMTYPE_TOPAZ:
- /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
+ /* SELECT SuperIO CHIP FOR QUERYING
+ (WRITE 0x07 TO BOTH 0x2E and 0x2F) */
outb(0x07, 0x2e);
outb(0x07, 0x2f);
@@ -154,14 +169,26 @@ static int __init asr_get_base_address(void)
case ASMTYPE_JASPER:
type = "Jaspers ";
-
- /* FIXME: need to use pci_config_lock here, but it's not exported */
+#if 0
+ u32 r;
+ /* Suggested fix */
+ pdev = pci_get_bus_and_slot(0, DEVFN(0x1f, 0));
+ if (pdev == NULL)
+ return -ENODEV;
+ pci_read_config_dword(pdev, 0x58, &r);
+ asr_base = r & 0xFFFE;
+ pci_dev_put(pdev);
+#else
+ /* FIXME: need to use pci_config_lock here,
+ but it's not exported */
/* spin_lock_irqsave(&pci_config_lock, flags);*/
/* Select the SuperIO chip in the PCI I/O port register */
outl(0x8000f858, 0xcf8);
+ /* BUS 0, Slot 1F, fnc 0, offset 58 */
+
/*
* Read the base address for the SuperIO chip.
* Only the lower 16 bits are valid, but the address is word
@@ -170,7 +197,7 @@ static int __init asr_get_base_address(void)
asr_base = inl(0xcfc) & 0xfffe;
/* spin_unlock_irqrestore(&pci_config_lock, flags);*/
-
+#endif
asr_read_addr = asr_write_addr =
asr_base + JASPER_ASR_REG_OFFSET;
asr_toggle_mask = JASPER_ASR_TOGGLE_MASK;
@@ -207,12 +234,11 @@ static int __init asr_get_base_address(void)
}
if (!request_region(asr_base, asr_length, "ibmasr")) {
- printk(KERN_ERR PFX "address %#x already in use\n",
- asr_base);
+ pr_err("address %#x already in use\n", asr_base);
return -EBUSY;
}
- printk(KERN_INFO PFX "found %sASR @ addr %#x\n", type, asr_base);
+ pr_info("found %sASR @ addr %#x\n", type, asr_base);
return 0;
}
@@ -241,66 +267,57 @@ static ssize_t asr_write(struct file *file, const char __user *buf,
return count;
}
-static int asr_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
+static long asr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
static const struct watchdog_info ident = {
- .options = WDIOF_KEEPALIVEPING |
+ .options = WDIOF_KEEPALIVEPING |
WDIOF_MAGICCLOSE,
- .identity = "IBM ASR"
+ .identity = "IBM ASR",
};
void __user *argp = (void __user *)arg;
int __user *p = argp;
int heartbeat;
switch (cmd) {
- case WDIOC_GETSUPPORT:
- return copy_to_user(argp, &ident, sizeof(ident)) ?
- -EFAULT : 0;
-
- case WDIOC_GETSTATUS:
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
-
- case WDIOC_KEEPALIVE:
+ case WDIOC_GETSUPPORT:
+ return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0;
+ case WDIOC_GETSTATUS:
+ case WDIOC_GETBOOTSTATUS:
+ return put_user(0, p);
+ case WDIOC_SETOPTIONS:
+ {
+ int new_options, retval = -EINVAL;
+ if (get_user(new_options, p))
+ return -EFAULT;
+ if (new_options & WDIOS_DISABLECARD) {
+ asr_disable();
+ retval = 0;
+ }
+ if (new_options & WDIOS_ENABLECARD) {
+ asr_enable();
asr_toggle();
- return 0;
-
- /*
- * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
- * and WDIOC_GETTIMEOUT always returns 256.
- */
- case WDIOC_GETTIMEOUT:
- heartbeat = 256;
- return put_user(heartbeat, p);
-
- case WDIOC_SETOPTIONS: {
- int new_options, retval = -EINVAL;
-
- if (get_user(new_options, p))
- return -EFAULT;
-
- if (new_options & WDIOS_DISABLECARD) {
- asr_disable();
- retval = 0;
- }
-
- if (new_options & WDIOS_ENABLECARD) {
- asr_enable();
- asr_toggle();
- retval = 0;
- }
-
- return retval;
+ retval = 0;
}
+ return retval;
+ }
+ case WDIOC_KEEPALIVE:
+ asr_toggle();
+ return 0;
+ /*
+ * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT
+ * and WDIOC_GETTIMEOUT always returns 256.
+ */
+ case WDIOC_GETTIMEOUT:
+ heartbeat = 256;
+ return put_user(heartbeat, p);
+ default:
+ return -ENOTTY;
}
-
- return -ENOTTY;
}
static int asr_open(struct inode *inode, struct file *file)
{
- if(test_and_set_bit(0, &asr_is_open))
+ if (test_and_set_bit(0, &asr_is_open))
return -EBUSY;
asr_toggle();
@@ -314,7 +331,7 @@ static int asr_release(struct inode *inode, struct file *file)
if (asr_expect_close == 42)
asr_disable();
else {
- printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n");
+ pr_crit("unexpected close, not stopping watchdog!\n");
asr_toggle();
}
clear_bit(0, &asr_is_open);
@@ -323,12 +340,12 @@ static int asr_release(struct inode *inode, struct file *file)
}
static const struct file_operations asr_fops = {
- .owner = THIS_MODULE,
- .llseek = no_llseek,
- .write = asr_write,
- .ioctl = asr_ioctl,
- .open = asr_open,
- .release = asr_release,
+ .owner = THIS_MODULE,
+ .llseek = no_llseek,
+ .write = asr_write,
+ .unlocked_ioctl = asr_ioctl,
+ .open = asr_open,
+ .release = asr_release,
};
static struct miscdevice asr_miscdev = {
@@ -343,7 +360,7 @@ struct ibmasr_id {
int type;
};
-static struct ibmasr_id __initdata ibmasr_id_table[] = {
+static struct ibmasr_id ibmasr_id_table[] __initdata = {
{ "IBM Automatic Server Restart - eserver xSeries 220", ASMTYPE_TOPAZ },
{ "IBM Automatic Server Restart - Machine Type 8673", ASMTYPE_PEARL },
{ "IBM Automatic Server Restart - Machine Type 8480", ASMTYPE_JASPER },
@@ -374,7 +391,7 @@ static int __init ibmasr_init(void)
rc = misc_register(&asr_miscdev);
if (rc < 0) {
release_region(asr_base, asr_length);
- printk(KERN_ERR PFX "failed to register misc device\n");
+ pr_err("failed to register misc device\n");
return rc;
}
@@ -394,10 +411,11 @@ static void __exit ibmasr_exit(void)
module_init(ibmasr_init);
module_exit(ibmasr_exit);
-module_param(nowayout, int, 0);
-MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout,
+ "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
MODULE_DESCRIPTION("IBM Automatic Server Restart driver");
MODULE_AUTHOR("Andrey Panin");
MODULE_LICENSE("GPL");
-MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);