Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88d5a7bb authored by Wim Van Sebroeck's avatar Wim Van Sebroeck
Browse files

Merge ../linux-2.6-watchdog-mm

parents 9af9fc45 82eb7c50
Loading
Loading
Loading
Loading
+88 −67
Original line number Diff line number Diff line
@@ -48,46 +48,52 @@
 *		It can be 1, 2, 10, 20, 110 or 220 seconds.
 */

#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/types.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/init.h>

#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>
/*
 *	Includes, defines, variables, module parameters, ...
 */

/* Includes */
#include <linux/module.h>		/* For module specific items */
#include <linux/moduleparam.h>		/* For new moduleparam's */
#include <linux/types.h>		/* For standard types (like size_t) */
#include <linux/errno.h>		/* For the -ENODEV/... values */
#include <linux/kernel.h>		/* For printk/panic/... */
#include <linux/miscdevice.h>		/* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */
#include <linux/watchdog.h>		/* For the watchdog specific items */
#include <linux/fs.h>			/* For file operations */
#include <linux/ioport.h>		/* For io-port access */
#include <linux/platform_device.h>	/* For platform_driver framework */
#include <linux/init.h>			/* For __init/__exit/... */

#include <asm/uaccess.h>		/* For copy_to_user/put_user/... */
#include <asm/io.h>			/* For inb/outb/... */

/* Module information */
#define DRV_NAME "acquirewdt"
#define PFX DRV_NAME ": "
#define WATCHDOG_NAME "Acquire WDT"
#define PFX WATCHDOG_NAME ": "
#define WATCHDOG_HEARTBEAT 0	/* There is no way to see what the correct time-out period is */

/* internal variables */
static struct platform_device *acq_platform_device;	/* the watchdog platform device */
static unsigned long acq_is_open;
static char expect_close;

/*
 *	You must set these - there is no sane way to probe for this board.
 */

static int wdt_stop = 0x43;
/* module parameters */
static int wdt_stop = 0x43;	/* You must set this - there is no sane way to probe for this board. */
module_param(wdt_stop, int, 0);
MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)");

static int wdt_start = 0x443;
static int wdt_start = 0x443;	/* You must set this - there is no sane way to probe for this board. */
module_param(wdt_start, int, 0);
MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");

static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

/*
 *	Kernel methods.
 *	Watchdog Operations
 */

static void acq_keepalive(void)
@@ -103,7 +109,7 @@ static void acq_stop(void)
}

/*
 *	/dev/watchdog handling.
 *	/dev/watchdog handling
 */

static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
@@ -143,7 +149,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	{
		.options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "Acquire WDT",
		.identity = WATCHDOG_NAME,
	};

	switch(cmd)
@@ -213,20 +219,6 @@ static int acq_close(struct inode *inode, struct file *file)
	return 0;
}

/*
 *	Notifier for system down
 */

static int acq_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if(code==SYS_DOWN || code==SYS_HALT) {
		/* Turn the WDT off */
		acq_stop();
	}
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */
@@ -240,29 +232,20 @@ static const struct file_operations acq_fops = {
	.release	= acq_close,
};

static struct miscdevice acq_miscdev=
{
static struct miscdevice acq_miscdev = {
	.minor	= WATCHDOG_MINOR,
	.name	= "watchdog",
	.fops	= &acq_fops,
};

/*
 *	The WDT card needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 *	Init & exit routines
 */

static struct notifier_block acq_notifier =
{
	.notifier_call = acq_notify_sys,
};

static int __init acq_init(void)
static int __devinit acq_probe(struct platform_device *dev)
{
	int ret;

	printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");

	if (wdt_stop != wdt_start) {
		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -279,18 +262,11 @@ static int __init acq_init(void)
		goto unreg_stop;
	}

	ret = register_reboot_notifier(&acq_notifier);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			ret);
		goto unreg_regions;
	}

	ret = misc_register(&acq_miscdev);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		goto unreg_reboot;
		goto unreg_regions;
	}

	printk (KERN_INFO PFX "initialized. (nowayout=%d)\n",
@@ -298,8 +274,6 @@ static int __init acq_init(void)

	return 0;

unreg_reboot:
	unregister_reboot_notifier(&acq_notifier);
unreg_regions:
	release_region(wdt_start, 1);
unreg_stop:
@@ -309,13 +283,60 @@ out:
	return ret;
}

static void __exit acq_exit(void)
static int __devexit acq_remove(struct platform_device *dev)
{
	misc_deregister(&acq_miscdev);
	unregister_reboot_notifier(&acq_notifier);
	release_region(wdt_start,1);
	if(wdt_stop != wdt_start)
		release_region(wdt_stop,1);
	release_region(wdt_start,1);

	return 0;
}

static void acq_shutdown(struct platform_device *dev)
{
	/* Turn the WDT off if we have a soft shutdown */
	acq_stop();
}

static struct platform_driver acquirewdt_driver = {
	.probe		= acq_probe,
	.remove		= __devexit_p(acq_remove),
	.shutdown	= acq_shutdown,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= DRV_NAME,
	},
};

static int __init acq_init(void)
{
	int err;

	printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n");

	err = platform_driver_register(&acquirewdt_driver);
	if (err)
		return err;

	acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
	if (IS_ERR(acq_platform_device)) {
		err = PTR_ERR(acq_platform_device);
		goto unreg_platform_driver;
	}

	return 0;

unreg_platform_driver:
	platform_driver_unregister(&acquirewdt_driver);
	return err;
}

static void __exit acq_exit(void)
{
	platform_device_unregister(acq_platform_device);
	platform_driver_unregister(&acquirewdt_driver);
	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
}

module_init(acq_init);
+88 −54
Original line number Diff line number Diff line
@@ -35,18 +35,19 @@
#include <linux/watchdog.h>
#include <linux/fs.h>
#include <linux/ioport.h>
#include <linux/notifier.h>
#include <linux/reboot.h>
#include <linux/platform_device.h>
#include <linux/init.h>

#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/system.h>

#define DRV_NAME "advantechwdt"
#define PFX DRV_NAME ": "
#define WATCHDOG_NAME "Advantech WDT"
#define PFX WATCHDOG_NAME ": "
#define WATCHDOG_TIMEOUT 60		/* 60 sec default timeout */

static struct platform_device *advwdt_platform_device;	/* the watchdog platform device */
static unsigned long advwdt_is_open;
static char adv_expect_close;

@@ -75,10 +76,10 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, defaul

static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

/*
 *	Kernel methods.
 *	Watchdog Operations
 */

static void
@@ -94,6 +95,20 @@ advwdt_disable(void)
	inb_p(wdt_stop);
}

static int
advwdt_set_heartbeat(int t)
{
	if ((t < 1) || (t > 63))
		return -EINVAL;

	timeout = t;
	return 0;
}

/*
 *	/dev/watchdog handling
 */

static ssize_t
advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{
@@ -126,7 +141,7 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	static struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "Advantech WDT",
		.identity = WATCHDOG_NAME,
	};

	switch (cmd) {
@@ -146,9 +161,8 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
	case WDIOC_SETTIMEOUT:
	  if (get_user(new_timeout, p))
		  return -EFAULT;
	  if ((new_timeout < 1) || (new_timeout > 63))
	  if (advwdt_set_heartbeat(new_timeout))
		  return -EINVAL;
	  timeout = new_timeout;
	  advwdt_ping();
	  /* Fall */

@@ -208,21 +222,6 @@ advwdt_close(struct inode *inode, struct file *file)
	return 0;
}

/*
 *	Notifier for system down
 */

static int
advwdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT) {
		/* Turn the WDT off */
		advwdt_disable();
	}
	return NOTIFY_DONE;
}

/*
 *	Kernel Interfaces
 */
@@ -243,27 +242,14 @@ static struct miscdevice advwdt_miscdev = {
};

/*
 *	The WDT needs to learn about soft shutdowns in order to
 *	turn the timebomb registers off.
 *	Init & exit routines
 */

static struct notifier_block advwdt_notifier = {
	.notifier_call = advwdt_notify_sys,
};

static int __init
advwdt_init(void)
static int __devinit
advwdt_probe(struct platform_device *dev)
{
	int ret;

	printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");

	if (timeout < 1 || timeout > 63) {
		timeout = WATCHDOG_TIMEOUT;
		printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
			timeout);
	}

	if (wdt_stop != wdt_start) {
		if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) {
			printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -280,18 +266,18 @@ advwdt_init(void)
		goto unreg_stop;
	}

	ret = register_reboot_notifier(&advwdt_notifier);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n",
			ret);
		goto unreg_regions;
	/* Check that the heartbeat value is within it's range ; if not reset to the default */
	if (advwdt_set_heartbeat(timeout)) {
		advwdt_set_heartbeat(WATCHDOG_TIMEOUT);
		printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n",
			timeout);
	}

	ret = misc_register(&advwdt_miscdev);
	if (ret != 0) {
		printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		goto unreg_reboot;
		goto unreg_regions;
	}

	printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n",
@@ -299,8 +285,6 @@ advwdt_init(void)

out:
	return ret;
unreg_reboot:
	unregister_reboot_notifier(&advwdt_notifier);
unreg_regions:
	release_region(wdt_start, 1);
unreg_stop:
@@ -309,14 +293,64 @@ unreg_stop:
	goto out;
}

static void __exit
advwdt_exit(void)
static int __devexit
advwdt_remove(struct platform_device *dev)
{
	misc_deregister(&advwdt_miscdev);
	unregister_reboot_notifier(&advwdt_notifier);
	release_region(wdt_start,1);
	if(wdt_stop != wdt_start)
		release_region(wdt_stop,1);
	release_region(wdt_start,1);

	return 0;
}

static void
advwdt_shutdown(struct platform_device *dev)
{
	/* Turn the WDT off if we have a soft shutdown */
	advwdt_disable();
}

static struct platform_driver advwdt_driver = {
	.probe		= advwdt_probe,
	.remove		= __devexit_p(advwdt_remove),
	.shutdown	= advwdt_shutdown,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= DRV_NAME,
	},
};

static int __init
advwdt_init(void)
{
	int err;

	printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n");

	err = platform_driver_register(&advwdt_driver);
	if (err)
		return err;

	advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0);
	if (IS_ERR(advwdt_platform_device)) {
		err = PTR_ERR(advwdt_platform_device);
		goto unreg_platform_driver;
	}

	return 0;

unreg_platform_driver:
	platform_driver_unregister(&advwdt_driver);
	return err;
}

static void __exit
advwdt_exit(void)
{
	platform_device_unregister(advwdt_platform_device);
	platform_driver_unregister(&advwdt_driver);
	printk(KERN_INFO PFX "Watchdog Module Unloaded.\n");
}

module_init(advwdt_init);
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, defaul

static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

/*
 *	ali_start	-	start watchdog countdown
+4 −11
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@ module_param(use_gpio, int, 0);
MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog.  (required by old cobalt boards)");

static void wdt_timer_ping(unsigned long);
static struct timer_list timer;
static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1);
static unsigned long next_heartbeat;
static unsigned long wdt_is_open;
static char wdt_expect_close;
@@ -78,7 +78,7 @@ static struct pci_dev *alim7101_pmu;
static int nowayout = WATCHDOG_NOWAYOUT;
module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
		 __stringify(CONFIG_WATCHDOG_NOWAYOUT) ")");
		 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");

/*
 *	Whack the dog
@@ -108,8 +108,7 @@ static void wdt_timer_ping(unsigned long data)
		printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n");
	}
	/* Re-set the timer interval */
	timer.expires = jiffies + WDT_INTERVAL;
	add_timer(&timer);
	mod_timer(&timer, jiffies + WDT_INTERVAL);
}

/*
@@ -147,9 +146,7 @@ static void wdt_startup(void)
	wdt_change(WDT_ENABLE);

	/* Start the timer */
	timer.expires = jiffies + WDT_INTERVAL;
	add_timer(&timer);

	mod_timer(&timer, jiffies + WDT_INTERVAL);

	printk(KERN_INFO PFX "Watchdog timer is now enabled.\n");
}
@@ -380,10 +377,6 @@ static int __init alim7101_wdt_init(void)
			timeout);
	}

	init_timer(&timer);
	timer.function = wdt_timer_ping;
	timer.data = 1;

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n",
+4 −9
Original line number Diff line number Diff line
@@ -80,10 +80,8 @@ static void cpu5wdt_trigger(unsigned long unused)
	outb(1, port + CPU5WDT_TRIGGER_REG);

	/* requeue?? */
	if( cpu5wdt_device.queue && ticks ) {
		cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL;
		add_timer(&cpu5wdt_device.timer);
	}
	if (cpu5wdt_device.queue && ticks)
		mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
	else {
		/* ticks doesn't matter anyway */
		complete(&cpu5wdt_device.stop);
@@ -109,8 +107,7 @@ static void cpu5wdt_start(void)
		outb(1, port + CPU5WDT_MODE_REG);
		outb(0, port + CPU5WDT_RESET_REG);
		outb(0, port + CPU5WDT_ENABLE_REG);
		cpu5wdt_device.timer.expires = jiffies + CPU5WDT_INTERVAL;
		add_timer(&cpu5wdt_device.timer);
		mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
	}
	/* if process dies, counter is not decremented */
	cpu5wdt_device.running++;
@@ -245,9 +242,7 @@ static int __devinit cpu5wdt_init(void)

	clear_bit(0, &cpu5wdt_device.inuse);

	init_timer(&cpu5wdt_device.timer);
	cpu5wdt_device.timer.function = cpu5wdt_trigger;
	cpu5wdt_device.timer.data = 0;
	setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);

	cpu5wdt_device.default_ticks = ticks;

Loading