[WATCHDOG 44/57] scx200_wdt: clean up and switch to unlocked_ioctl

Review and switch to unlocked_ioctl

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
This commit is contained in:
Alan Cox 2008-05-19 14:08:49 +01:00 committed by Wim Van Sebroeck
parent ff94806057
commit 9b748ed03c
2 changed files with 32 additions and 31 deletions

View File

@ -279,7 +279,7 @@ static int fop_close(struct inode *inode, struct file *file)
return 0; return 0;
} }
static int fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
@ -345,7 +345,7 @@ static const struct file_operations wdt_fops = {
.write = fop_write, .write = fop_write,
.open = fop_open, .open = fop_open,
.release = fop_close, .release = fop_close,
.ioctl = fop_ioctl, .unlocked_ioctl = fop_ioctl,
}; };
static struct miscdevice wdt_miscdev = { static struct miscdevice wdt_miscdev = {

View File

@ -27,9 +27,8 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/scx200.h> #include <linux/scx200.h>
#include <linux/uaccess.h>
#include <asm/uaccess.h> #include <linux/io.h>
#include <asm/io.h>
#define NAME "scx200_wdt" #define NAME "scx200_wdt"
@ -47,8 +46,9 @@ module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
static u16 wdto_restart; static u16 wdto_restart;
static struct semaphore open_semaphore;
static char expect_close; static char expect_close;
static unsigned long open_lock;
static DEFINE_SPINLOCK(scx_lock);
/* Bits of the WDCNFG register */ /* Bits of the WDCNFG register */
#define W_ENABLE 0x00fa /* Enable watchdog */ #define W_ENABLE 0x00fa /* Enable watchdog */
@ -59,7 +59,9 @@ static char expect_close;
static void scx200_wdt_ping(void) static void scx200_wdt_ping(void)
{ {
spin_lock(&scx_lock);
outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO); outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO);
spin_unlock(&scx_lock);
} }
static void scx200_wdt_update_margin(void) static void scx200_wdt_update_margin(void)
@ -73,9 +75,11 @@ static void scx200_wdt_enable(void)
printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n",
wdto_restart); wdto_restart);
spin_lock(&scx_lock);
outw(0, scx200_cb_base + SCx200_WDT_WDTO); outw(0, scx200_cb_base + SCx200_WDT_WDTO);
outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG); outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
spin_unlock(&scx_lock);
scx200_wdt_ping(); scx200_wdt_ping();
} }
@ -84,15 +88,17 @@ static void scx200_wdt_disable(void)
{ {
printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); printk(KERN_DEBUG NAME ": disabling watchdog timer\n");
spin_lock(&scx_lock);
outw(0, scx200_cb_base + SCx200_WDT_WDTO); outw(0, scx200_cb_base + SCx200_WDT_WDTO);
outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS);
outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG); outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG);
spin_unlock(&scx_lock);
} }
static int scx200_wdt_open(struct inode *inode, struct file *file) static int scx200_wdt_open(struct inode *inode, struct file *file)
{ {
/* only allow one at a time */ /* only allow one at a time */
if (down_trylock(&open_semaphore)) if (test_and_set_bit(0, &open_lock))
return -EBUSY; return -EBUSY;
scx200_wdt_enable(); scx200_wdt_enable();
@ -101,13 +107,12 @@ static int scx200_wdt_open(struct inode *inode, struct file *file)
static int scx200_wdt_release(struct inode *inode, struct file *file) static int scx200_wdt_release(struct inode *inode, struct file *file)
{ {
if (expect_close != 42) { if (expect_close != 42)
printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n"); printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n");
} else if (!nowayout) { else if (!nowayout)
scx200_wdt_disable(); scx200_wdt_disable();
}
expect_close = 0; expect_close = 0;
up(&open_semaphore); clear_bit(0, &open_lock);
return 0; return 0;
} }
@ -122,8 +127,7 @@ static int scx200_wdt_notify_sys(struct notifier_block *this,
return NOTIFY_DONE; return NOTIFY_DONE;
} }
static struct notifier_block scx200_wdt_notifier = static struct notifier_block scx200_wdt_notifier = {
{
.notifier_call = scx200_wdt_notify_sys, .notifier_call = scx200_wdt_notify_sys,
}; };
@ -131,8 +135,7 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
size_t len, loff_t *ppos) size_t len, loff_t *ppos)
{ {
/* check for a magic close character */ /* check for a magic close character */
if (len) if (len) {
{
size_t i; size_t i;
scx200_wdt_ping(); scx200_wdt_ping();
@ -152,15 +155,15 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data,
return 0; return 0;
} }
static int scx200_wdt_ioctl(struct inode *inode, struct file *file, static long scx200_wdt_ioctl(struct file *file, unsigned int cmd,
unsigned int cmd, unsigned long arg) unsigned long arg)
{ {
void __user *argp = (void __user *)arg; void __user *argp = (void __user *)arg;
int __user *p = argp; int __user *p = argp;
static struct watchdog_info ident = { static const struct watchdog_info ident = {
.identity = "NatSemi SCx200 Watchdog", .identity = "NatSemi SCx200 Watchdog",
.firmware_version = 1, .firmware_version = 1,
.options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING), .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
}; };
int new_margin; int new_margin;
@ -168,7 +171,7 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
default: default:
return -ENOTTY; return -ENOTTY;
case WDIOC_GETSUPPORT: case WDIOC_GETSUPPORT:
if(copy_to_user(argp, &ident, sizeof(ident))) if (copy_to_user(argp, &ident, sizeof(ident)))
return -EFAULT; return -EFAULT;
return 0; return 0;
case WDIOC_GETSTATUS: case WDIOC_GETSTATUS:
@ -195,18 +198,18 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file,
} }
static const struct file_operations scx200_wdt_fops = { static const struct file_operations scx200_wdt_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.llseek = no_llseek, .llseek = no_llseek,
.write = scx200_wdt_write, .write = scx200_wdt_write,
.ioctl = scx200_wdt_ioctl, .unlocked_ioctl = scx200_wdt_ioctl,
.open = scx200_wdt_open, .open = scx200_wdt_open,
.release = scx200_wdt_release, .release = scx200_wdt_release,
}; };
static struct miscdevice scx200_wdt_miscdev = { static struct miscdevice scx200_wdt_miscdev = {
.minor = WATCHDOG_MINOR, .minor = WATCHDOG_MINOR,
.name = "watchdog", .name = "watchdog",
.fops = &scx200_wdt_fops, .fops = &scx200_wdt_fops,
}; };
static int __init scx200_wdt_init(void) static int __init scx200_wdt_init(void)
@ -229,8 +232,6 @@ static int __init scx200_wdt_init(void)
scx200_wdt_update_margin(); scx200_wdt_update_margin();
scx200_wdt_disable(); scx200_wdt_disable();
sema_init(&open_semaphore, 1);
r = register_reboot_notifier(&scx200_wdt_notifier); r = register_reboot_notifier(&scx200_wdt_notifier);
if (r) { if (r) {
printk(KERN_ERR NAME ": unable to register reboot notifier"); printk(KERN_ERR NAME ": unable to register reboot notifier");
@ -263,7 +264,7 @@ module_exit(scx200_wdt_cleanup);
/* /*
Local variables: Local variables:
compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules"
c-basic-offset: 8 c-basic-offset: 8
End: End:
*/ */