Beispiel #1
0
static long pc87413_ioctl(struct file *file, unsigned int cmd,
						unsigned long arg)
{
	int new_timeout;

	union {
		struct watchdog_info __user *ident;
		int __user *i;
	} uarg;

	static struct watchdog_info ident = {
		.options          = WDIOF_KEEPALIVEPING |
				    WDIOF_SETTIMEOUT |
				    WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity         = "PC87413(HF/F) watchdog",
	};

	uarg.i = (int __user *)arg;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(uarg.ident, &ident,
					sizeof(ident)) ? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		return put_user(pc87413_status(), uarg.i);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, uarg.i);
	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;
		if (get_user(options, uarg.i))
			return -EFAULT;
		if (options & WDIOS_DISABLECARD) {
			pc87413_disable();
			retval = 0;
		}
		if (options & WDIOS_ENABLECARD) {
			pc87413_enable();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		pc87413_refresh();
#ifdef DEBUG
		printk(KERN_INFO DPFX "keepalive\n");
#endif
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, uarg.i))
			return -EFAULT;
		/* the API states this is given in secs */
		new_timeout /= 60;
		if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
			return -EINVAL;
		timeout = new_timeout;
		pc87413_refresh();
		/* fall through and return the new timeout... */
	case WDIOC_GETTIMEOUT:
		new_timeout = timeout * 60;
		return put_user(new_timeout, uarg.i);
	default:
		return -ENOTTY;
	}
}

/* -- Notifier funtions -----------------------------------------*/

/**
 *	notify_sys:
 *	@this: our notifier block
 *	@code: the event being reported
 *	@unused: unused
 *
 *	Our notifier is called on system shutdowns. We want to turn the card
 *	off at reboot otherwise the machine will reboot again during memory
 *	test or worse yet during the following fsck. This would suck, in fact
 *	trust me - if it happens it does suck.
 */

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

/* -- Module's structures ---------------------------------------*/

static const struct file_operations pc87413_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= pc87413_write,
	.unlocked_ioctl	= pc87413_ioctl,
	.open		= pc87413_open,
	.release	= pc87413_release,
};

static struct notifier_block pc87413_notifier = {
	.notifier_call  = pc87413_notify_sys,
};

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

/* -- Module init functions -------------------------------------*/

/**
 * 	pc87413_init: module's "constructor"
 *
 *	Set up the WDT watchdog board. All we have to do is grab the
 *	resources we require and bitch if anyone beat us to them.
 *	The open() function will actually kick the board off.
 */

static int __init pc87413_init(void)
{
	int ret;

	printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n",
							WDT_INDEX_IO_PORT);

	/* request_region(io, 2, "pc87413"); */

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

	ret = misc_register(&pc87413_miscdev);
	if (ret != 0) {
		printk(KERN_ERR PFX
			"cannot register miscdev on minor=%d (err=%d)\n",
			WATCHDOG_MINOR, ret);
		unregister_reboot_notifier(&pc87413_notifier);
		return ret;
	}
	printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout);
	pc87413_enable();
	return 0;
}

/**
 *	pc87413_exit: module's "destructor"
 *
 *	Unload the watchdog. You cannot do this with any file handles open.
 *	If your watchdog is set to continue ticking on close and you unload
 *	it, well it keeps ticking. We won't get the interrupt but the board
 *	will not touch PC memory so all is fine. You just have to load a new
 *	module in 60 seconds or reboot.
 */

static void __exit pc87413_exit(void)
{
	/* Stop the timer before we leave */
	if (!nowayout) {
		pc87413_disable();
		printk(KERN_INFO MODNAME "Watchdog disabled.\n");
	}

	misc_deregister(&pc87413_miscdev);
	unregister_reboot_notifier(&pc87413_notifier);
	/* release_region(io, 2); */

	printk(KERN_INFO MODNAME " watchdog component driver removed.\n");
}

module_init(pc87413_init);
module_exit(pc87413_exit);

MODULE_AUTHOR("Sven Anders <*****@*****.**>, "
		"Marcus Junker <*****@*****.**>,");
MODULE_DESCRIPTION("PC87413 WDT driver");
MODULE_LICENSE("GPL");

MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

module_param(io, int, 0);
MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ").");

module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout,
		"Watchdog timeout in minutes (default="
				__MODULE_STRING(timeout) ").");

module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout,
		"Watchdog cannot be stopped once started (default="
				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = argp;
	static const struct watchdog_info ident = {
		.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT
							| WDIOF_MAGICCLOSE,
		.firmware_version = 1,
		.identity = "SC520",
	};

	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_SETOPTIONS:
	{
		int new_options, retval = -EINVAL;

		if (get_user(new_options, p))
			return -EFAULT;

		if (new_options & WDIOS_DISABLECARD) {
			wdt_turnoff();
			retval = 0;
		}

		if (new_options & WDIOS_ENABLECARD) {
			wdt_startup();
			retval = 0;
		}

		return retval;
	}
	case WDIOC_KEEPALIVE:
		wdt_keepalive();
		return 0;
	case WDIOC_SETTIMEOUT:
	{
		int new_timeout;

		if (get_user(new_timeout, p))
			return -EFAULT;

		if (wdt_set_heartbeat(new_timeout))
			return -EINVAL;

		wdt_keepalive();
		
	}
	case WDIOC_GETTIMEOUT:
		return put_user(timeout, p);
	default:
		return -ENOTTY;
	}
}

static const struct file_operations wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.write		= fop_write,
	.open		= fop_open,
	.release	= fop_close,
	.unlocked_ioctl	= fop_ioctl,
};

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


static int wdt_notify_sys(struct notifier_block *this, unsigned long code,
	void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT)
		wdt_turnoff();
	return NOTIFY_DONE;
}


static struct notifier_block wdt_notifier = {
	.notifier_call = wdt_notify_sys,
};

static void __exit sc520_wdt_unload(void)
{
	if (!nowayout)
		wdt_turnoff();

	
	misc_deregister(&wdt_miscdev);
	unregister_reboot_notifier(&wdt_notifier);
	iounmap(wdtmrctl);
}

static int __init sc520_wdt_init(void)
{
	int rc = -EBUSY;

	if (wdt_set_heartbeat(timeout)) {
		wdt_set_heartbeat(WATCHDOG_TIMEOUT);
		pr_info("timeout value must be 1 <= timeout <= 3600, using %d\n",
			WATCHDOG_TIMEOUT);
	}

	wdtmrctl = ioremap(MMCR_BASE + OFFS_WDTMRCTL, 2);
	if (!wdtmrctl) {
		pr_err("Unable to remap memory\n");
		rc = -ENOMEM;
		goto err_out_region2;
	}

	rc = register_reboot_notifier(&wdt_notifier);
	if (rc) {
		pr_err("cannot register reboot notifier (err=%d)\n", rc);
		goto err_out_ioremap;
	}

	rc = misc_register(&wdt_miscdev);
	if (rc) {
		pr_err("cannot register miscdev on minor=%d (err=%d)\n",
		       WATCHDOG_MINOR, rc);
		goto err_out_notifier;
	}

	pr_info("WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n",
		timeout, nowayout);

	return 0;

err_out_notifier:
	unregister_reboot_notifier(&wdt_notifier);
err_out_ioremap:
	iounmap(wdtmrctl);
err_out_region2:
	return rc;
}

module_init(sc520_wdt_init);
module_exit(sc520_wdt_unload);

MODULE_AUTHOR("Scott and Bill Jennings");
MODULE_DESCRIPTION(
	"Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
static long wb_smsc_wdt_ioctl(struct file *file,
					unsigned int cmd, unsigned long arg)
{
	int new_timeout;

	union {
		struct watchdog_info __user *ident;
		int __user *i;
	} uarg;

	static const struct watchdog_info ident = {
		.options =		WDIOF_KEEPALIVEPING |
					WDIOF_SETTIMEOUT |
					WDIOF_MAGICCLOSE,
		.firmware_version =	0,
		.identity =		"SMsC 37B787 Watchdog",
	};

	uarg.i = (int __user *)arg;

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		return copy_to_user(uarg.ident, &ident, sizeof(ident))
								? -EFAULT : 0;
	case WDIOC_GETSTATUS:
		return put_user(wb_smsc_wdt_status(), uarg.i);
	case WDIOC_GETBOOTSTATUS:
		return put_user(0, uarg.i);
	case WDIOC_SETOPTIONS:
	{
		int options, retval = -EINVAL;

		if (get_user(options, uarg.i))
			return -EFAULT;

		if (options & WDIOS_DISABLECARD) {
			wb_smsc_wdt_disable();
			retval = 0;
		}
		if (options & WDIOS_ENABLECARD) {
			wb_smsc_wdt_enable();
			retval = 0;
		}
		return retval;
	}
	case WDIOC_KEEPALIVE:
		wb_smsc_wdt_reset_timer();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_timeout, uarg.i))
			return -EFAULT;
		
		if (unit == UNIT_MINUTE)
			new_timeout /= 60;
		if (new_timeout < 0 || new_timeout > MAX_TIMEOUT)
			return -EINVAL;
		timeout = new_timeout;
		wb_smsc_wdt_set_timeout(timeout);
		
	case WDIOC_GETTIMEOUT:
		new_timeout = timeout;
		if (unit == UNIT_MINUTE)
			new_timeout *= 60;
		return put_user(new_timeout, uarg.i);
	default:
		return -ENOTTY;
	}
}


static int wb_smsc_wdt_notify_sys(struct notifier_block *this,
					unsigned long code, void *unused)
{
	if (code == SYS_DOWN || code == SYS_HALT) {
		
		timeout = 0;
		wb_smsc_wdt_disable();
	}
	return NOTIFY_DONE;
}


static const struct file_operations wb_smsc_wdt_fops = {
	.owner	  = THIS_MODULE,
	.llseek		= no_llseek,
	.write		= wb_smsc_wdt_write,
	.unlocked_ioctl	= wb_smsc_wdt_ioctl,
	.open		= wb_smsc_wdt_open,
	.release	= wb_smsc_wdt_release,
};

static struct notifier_block wb_smsc_wdt_notifier = {
	.notifier_call  = wb_smsc_wdt_notify_sys,
};

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



static int __init wb_smsc_wdt_init(void)
{
	int ret;

	pr_info("SMsC 37B787 watchdog component driver "
		VERSION " initialising...\n");

	if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) {
		pr_err("Unable to register IO port %#x\n", IOPORT);
		ret = -EBUSY;
		goto out_pnp;
	}

	
	if (timeout > MAX_TIMEOUT)
		timeout = MAX_TIMEOUT;

	
	wb_smsc_wdt_initialize();

	ret = register_reboot_notifier(&wb_smsc_wdt_notifier);
	if (ret) {
		pr_err("Unable to register reboot notifier err = %d\n", ret);
		goto out_io;
	}

	ret = misc_register(&wb_smsc_wdt_miscdev);
	if (ret) {
		pr_err("Unable to register miscdev on minor %d\n",
		       WATCHDOG_MINOR);
		goto out_rbt;
	}

	
	pr_info("Timeout set to %d %s\n",
		timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)");
	pr_info("Watchdog initialized and sleeping (nowayout=%d)...\n",
		nowayout);
out_clean:
	return ret;

out_rbt:
	unregister_reboot_notifier(&wb_smsc_wdt_notifier);

out_io:
	release_region(IOPORT, IOPORT_SIZE);

out_pnp:
	goto out_clean;
}


static void __exit wb_smsc_wdt_exit(void)
{
	
	if (!nowayout) {
		wb_smsc_wdt_shutdown();
		pr_info("Watchdog disabled\n");
	}

	misc_deregister(&wb_smsc_wdt_miscdev);
	unregister_reboot_notifier(&wb_smsc_wdt_notifier);
	release_region(IOPORT, IOPORT_SIZE);

	pr_info("SMsC 37B787 watchdog component driver removed\n");
}

module_init(wb_smsc_wdt_init);
module_exit(wb_smsc_wdt_exit);

MODULE_AUTHOR("Sven Anders <*****@*****.**>");
MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version "
								VERSION ")");
MODULE_LICENSE("GPL");

MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

#ifdef SMSC_SUPPORT_MINUTES
module_param(unit, int, 0);
MODULE_PARM_DESC(unit,
		"set unit to use, 0=seconds or 1=minutes, default is 0");
#endif

module_param(timeout, int, 0);
MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60");

module_param(nowayout, bool, 0);
MODULE_PARM_DESC(nowayout,
		"Watchdog cannot be stopped once started (default="
				__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
Beispiel #4
0
static int
omap_wdt_ioctl(struct inode *inode, struct file *file,
	unsigned int cmd, unsigned long arg)
{
	int new_margin;
	static struct watchdog_info ident = {
		.identity = "OMAP Watchdog",
		.options = WDIOF_SETTIMEOUT,
		.firmware_version = 0,
	};

	switch (cmd) {
	default:
		return -ENOTTY;
	case WDIOC_GETSUPPORT:
		return copy_to_user((struct watchdog_info __user *)arg, &ident,
				sizeof(ident));
	case WDIOC_GETSTATUS:
		return put_user(0, (int __user *)arg);
	case WDIOC_GETBOOTSTATUS:
		if (cpu_is_omap16xx())
			return put_user(omap_readw(ARM_SYSST),
					(int __user *)arg);
		if (cpu_is_omap24xx())
			return put_user(omap_prcm_get_reset_sources(),
					(int __user *)arg);
	case WDIOC_KEEPALIVE:
		omap_wdt_ping();
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_margin, (int __user *)arg))
			return -EFAULT;
		omap_wdt_adjust_timeout(new_margin);

		omap_wdt_disable();
		omap_wdt_set_timeout();
		omap_wdt_enable();

		omap_wdt_ping();
		/* Fall */
	case WDIOC_GETTIMEOUT:
		return put_user(timer_margin, (int __user *)arg);
	}
}

static const struct file_operations omap_wdt_fops = {
	.owner = THIS_MODULE,
	.write = omap_wdt_write,
	.ioctl = omap_wdt_ioctl,
	.open = omap_wdt_open,
	.release = omap_wdt_release,
};

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

static int __init omap_wdt_probe(struct platform_device *pdev)
{
	struct resource *res, *mem;
	int ret;

	/* reserve static register mappings */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res)
		return -ENOENT;

	mem = request_mem_region(res->start, res->end - res->start + 1,
				 pdev->name);
	if (mem == NULL)
		return -EBUSY;

	platform_set_drvdata(pdev, mem);

	omap_wdt_users = 0;

	if (cpu_is_omap16xx()) {
		armwdt_ck = clk_get(&pdev->dev, "armwdt_ck");
		if (IS_ERR(armwdt_ck)) {
			ret = PTR_ERR(armwdt_ck);
			armwdt_ck = NULL;
			goto fail;
		}
	}

	if (cpu_is_omap24xx()) {
		mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick");
		if (IS_ERR(mpu_wdt_ick)) {
			ret = PTR_ERR(mpu_wdt_ick);
			mpu_wdt_ick = NULL;
			goto fail;
		}
		mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck");
		if (IS_ERR(mpu_wdt_fck)) {
			ret = PTR_ERR(mpu_wdt_fck);
			mpu_wdt_fck = NULL;
			goto fail;
		}
	}

	omap_wdt_disable();
	omap_wdt_adjust_timeout(timer_margin);

	omap_wdt_miscdev.parent = &pdev->dev;
	ret = misc_register(&omap_wdt_miscdev);
	if (ret)
		goto fail;

	pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin);

	/* autogate OCP interface clock */
	omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG);
	return 0;

fail:
	if (armwdt_ck)
		clk_put(armwdt_ck);
	if (mpu_wdt_ick)
		clk_put(mpu_wdt_ick);
	if (mpu_wdt_fck)
		clk_put(mpu_wdt_fck);
	release_resource(mem);
	return ret;
}

static void omap_wdt_shutdown(struct platform_device *pdev)
{
	omap_wdt_disable();
}

static int omap_wdt_remove(struct platform_device *pdev)
{
	struct resource *mem = platform_get_drvdata(pdev);
	misc_deregister(&omap_wdt_miscdev);
	release_resource(mem);
	if (armwdt_ck)
		clk_put(armwdt_ck);
	if (mpu_wdt_ick)
		clk_put(mpu_wdt_ick);
	if (mpu_wdt_fck)
		clk_put(mpu_wdt_fck);
	return 0;
}

#ifdef	CONFIG_PM

/* REVISIT ... not clear this is the best way to handle system suspend; and
 * it's very inappropriate for selective device suspend (e.g. suspending this
 * through sysfs rather than by stopping the watchdog daemon).  Also, this
 * may not play well enough with NOWAYOUT...
 */

static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state)
{
	if (omap_wdt_users)
		omap_wdt_disable();
	return 0;
}

static int omap_wdt_resume(struct platform_device *pdev)
{
	if (omap_wdt_users) {
		omap_wdt_enable();
		omap_wdt_ping();
	}
	return 0;
}

#else
#define	omap_wdt_suspend	NULL
#define	omap_wdt_resume		NULL
#endif

static struct platform_driver omap_wdt_driver = {
	.probe		= omap_wdt_probe,
	.remove		= omap_wdt_remove,
	.shutdown	= omap_wdt_shutdown,
	.suspend	= omap_wdt_suspend,
	.resume		= omap_wdt_resume,
	.driver		= {
		.owner	= THIS_MODULE,
		.name	= "omap_wdt",
	},
};

static int __init omap_wdt_init(void)
{
	return platform_driver_register(&omap_wdt_driver);
}

static void __exit omap_wdt_exit(void)
{
	platform_driver_unregister(&omap_wdt_driver);
}

module_init(omap_wdt_init);
module_exit(omap_wdt_exit);

MODULE_AUTHOR("George G. Davis");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS("platform:omap_wdt");
Beispiel #5
0
static long asr_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	static const struct watchdog_info ident = {
		.options =	WDIOF_KEEPALIVEPING |
				WDIOF_MAGICCLOSE,
		.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_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;
	}
	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;
	}
}

static int asr_open(struct inode *inode, struct file *file)
{
	if (test_and_set_bit(0, &asr_is_open))
		return -EBUSY;

	asr_toggle();
	asr_enable();

	return nonseekable_open(inode, file);
}

static int asr_release(struct inode *inode, struct file *file)
{
	if (asr_expect_close == 42)
		asr_disable();
	else {
		pr_crit("unexpected close, not stopping watchdog!\n");
		asr_toggle();
	}
	clear_bit(0, &asr_is_open);
	asr_expect_close = 0;
	return 0;
}

static const struct file_operations asr_fops = {
	.owner =		THIS_MODULE,
	.llseek =		no_llseek,
	.write =		asr_write,
	.unlocked_ioctl =	asr_ioctl,
	.open =			asr_open,
	.release =		asr_release,
};

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


struct ibmasr_id {
	const char *desc;
	int type;
};

static struct ibmasr_id __initdata ibmasr_id_table[] = {
	{ "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 },
	{ "IBM Automatic Server Restart - Machine Type 8482", ASMTYPE_JUNIPER },
	{ "IBM Automatic Server Restart - Machine Type 8648", ASMTYPE_SPRUCE },
	{ NULL }
};

static int __init ibmasr_init(void)
{
	struct ibmasr_id *id;
	int rc;

	for (id = ibmasr_id_table; id->desc; id++) {
		if (dmi_find_device(DMI_DEV_TYPE_OTHER, id->desc, NULL)) {
			asr_type = id->type;
			break;
		}
	}

	if (!asr_type)
		return -ENODEV;

	rc = asr_get_base_address();
	if (rc)
		return rc;

	rc = misc_register(&asr_miscdev);
	if (rc < 0) {
		release_region(asr_base, asr_length);
		pr_err("failed to register misc device\n");
		return rc;
	}

	return 0;
}

static void __exit ibmasr_exit(void)
{
	if (!nowayout)
		asr_disable();

	misc_deregister(&asr_miscdev);

	release_region(asr_base, asr_length);
}

module_init(ibmasr_init);
module_exit(ibmasr_exit);

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);
static long mtx1_wdt_ioctl(struct file *file, unsigned int cmd,
							unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	int __user *p = (int __user *)argp;
	unsigned int value;
	static const struct watchdog_info ident = {
		.options = WDIOF_CARDRESET,
		.identity = "MTX-1 WDT",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;
	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		put_user(0, p);
		break;
	case WDIOC_SETOPTIONS:
		if (get_user(value, p))
			return -EFAULT;
		if (value & WDIOS_ENABLECARD)
			mtx1_wdt_start();
		else if (value & WDIOS_DISABLECARD)
			mtx1_wdt_stop();
		else
			return -EINVAL;
		return 0;
	case WDIOC_KEEPALIVE:
		mtx1_wdt_reset();
		break;
	default:
		return -ENOTTY;
	}
	return 0;
}


static ssize_t mtx1_wdt_write(struct file *file, const char *buf,
						size_t count, loff_t *ppos)
{
	if (!count)
		return -EIO;
	mtx1_wdt_reset();
	return count;
}

static const struct file_operations mtx1_wdt_fops = {
	.owner 		= THIS_MODULE,
	.llseek		= no_llseek,
	.unlocked_ioctl	= mtx1_wdt_ioctl,
	.open 		= mtx1_wdt_open,
	.write 		= mtx1_wdt_write,
	.release 	= mtx1_wdt_release,
};


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


static int mtx1_wdt_probe(struct platform_device *pdev)
{
	int ret;

	mtx1_wdt_device.gpio = pdev->resource[0].start;

	spin_lock_init(&mtx1_wdt_device.lock);
	init_completion(&mtx1_wdt_device.stop);
	mtx1_wdt_device.queue = 0;
	clear_bit(0, &mtx1_wdt_device.inuse);
	setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L);
	mtx1_wdt_device.default_ticks = ticks;

	ret = misc_register(&mtx1_wdt_misc);
	if (ret < 0) {
		printk(KERN_ERR " mtx-1_wdt : failed to register\n");
		return ret;
	}
	mtx1_wdt_start();
	printk(KERN_INFO "MTX-1 Watchdog driver\n");
	return 0;
}

static int mtx1_wdt_remove(struct platform_device *pdev)
{
	/* FIXME: do we need to lock this test ? */
	if (mtx1_wdt_device.queue) {
		mtx1_wdt_device.queue = 0;
		wait_for_completion(&mtx1_wdt_device.stop);
	}
	misc_deregister(&mtx1_wdt_misc);
	return 0;
}

static struct platform_driver mtx1_wdt = {
	.probe = mtx1_wdt_probe,
	.remove = mtx1_wdt_remove,
	.driver.name = "mtx1-wdt",
	.driver.owner = THIS_MODULE,
};

static int __init mtx1_wdt_init(void)
{
	return platform_driver_register(&mtx1_wdt);
}

static void __exit mtx1_wdt_exit(void)
{
	platform_driver_unregister(&mtx1_wdt);
}

module_init(mtx1_wdt_init);
module_exit(mtx1_wdt_exit);

MODULE_AUTHOR("Michael Stickel, Florian Fainelli");
MODULE_DESCRIPTION("Driver for the MTX-1 watchdog");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS("platform:mtx1-wdt");
Beispiel #7
0
static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file,
			    unsigned int cmd, unsigned long arg)
{
	int timeout;
	static struct watchdog_info info = {
		.options = WDIOF_KEEPALIVEPING,
		.firmware_version = 0,
		.identity = "MPC8xx watchdog",
	};

	switch (cmd) {
	case WDIOC_GETSUPPORT:
		if (copy_to_user((void *)arg, &info, sizeof(info)))
			return -EFAULT;
		break;

	case WDIOC_GETSTATUS:
	case WDIOC_GETBOOTSTATUS:
		if (put_user(wdt_status, (int *)arg))
			return -EFAULT;
		wdt_status &= ~WDIOF_KEEPALIVEPING;
		break;

	case WDIOC_GETTEMP:
		return -EOPNOTSUPP;

	case WDIOC_SETOPTIONS:
		return -EOPNOTSUPP;

	case WDIOC_KEEPALIVE:
		m8xx_wdt_reset();
		wdt_status |= WDIOF_KEEPALIVEPING;
		break;

	case WDIOC_SETTIMEOUT:
		return -EOPNOTSUPP;

	case WDIOC_GETTIMEOUT:
		timeout = m8xx_wdt_get_timeout();
		if (put_user(timeout, (int *)arg))
			return -EFAULT;
		break;

	default:
		return -ENOTTY;
	}

	return 0;
}

static const struct file_operations mpc8xx_wdt_fops = {
	.owner = THIS_MODULE,
	.llseek = no_llseek,
	.write = mpc8xx_wdt_write,
	.ioctl = mpc8xx_wdt_ioctl,
	.open = mpc8xx_wdt_open,
	.release = mpc8xx_wdt_release,
};

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

static int __init mpc8xx_wdt_init(void)
{
	return misc_register(&mpc8xx_wdt_miscdev);
}

static void __exit mpc8xx_wdt_exit(void)
{
	misc_deregister(&mpc8xx_wdt_miscdev);

	m8xx_wdt_reset();
	mpc8xx_wdt_handler_enable();
}

module_init(mpc8xx_wdt_init);
module_exit(mpc8xx_wdt_exit);

MODULE_AUTHOR("Florian Schirmer <*****@*****.**>");
MODULE_DESCRIPTION("MPC8xx watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
static long rdc321x_wdt_ioctl(struct file *file, unsigned int cmd,
				unsigned long arg)
{
	void __user *argp = (void __user *)arg;
	u32 value;
	static const struct watchdog_info ident = {
		.options = WDIOF_CARDRESET,
		.identity = "RDC321x WDT",
	};
	unsigned long flags;

	switch (cmd) {
	case WDIOC_KEEPALIVE:
		rdc321x_wdt_reset();
		break;
	case WDIOC_GETSTATUS:
		/*                                       */
		spin_lock_irqsave(&rdc321x_wdt_device.lock, flags);
		pci_read_config_dword(rdc321x_wdt_device.sb_pdev,
					rdc321x_wdt_device.base_reg, &value);
		spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags);
		if (copy_to_user(argp, &value, sizeof(u32)))
			return -EFAULT;
		break;
	case WDIOC_GETSUPPORT:
		if (copy_to_user(argp, &ident, sizeof(ident)))
			return -EFAULT;
		break;
	case WDIOC_SETOPTIONS:
		if (copy_from_user(&value, argp, sizeof(int)))
			return -EFAULT;
		switch (value) {
		case WDIOS_ENABLECARD:
			rdc321x_wdt_start();
			break;
		case WDIOS_DISABLECARD:
			return rdc321x_wdt_stop();
		default:
			return -EINVAL;
		}
		break;
	default:
		return -ENOTTY;
	}
	return 0;
}

static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf,
				size_t count, loff_t *ppos)
{
	if (!count)
		return -EIO;

	rdc321x_wdt_reset();

	return count;
}

static const struct file_operations rdc321x_wdt_fops = {
	.owner		= THIS_MODULE,
	.llseek		= no_llseek,
	.unlocked_ioctl	= rdc321x_wdt_ioctl,
	.open		= rdc321x_wdt_open,
	.write		= rdc321x_wdt_write,
	.release	= rdc321x_wdt_release,
};

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

static int __devinit rdc321x_wdt_probe(struct platform_device *pdev)
{
	int err;
	struct resource *r;
	struct rdc321x_wdt_pdata *pdata;

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data supplied\n");
		return -ENODEV;
	}

	r = platform_get_resource_byname(pdev, IORESOURCE_IO, "wdt-reg");
	if (!r) {
		dev_err(&pdev->dev, "failed to get wdt-reg resource\n");
		return -ENODEV;
	}

	rdc321x_wdt_device.sb_pdev = pdata->sb_pdev;
	rdc321x_wdt_device.base_reg = r->start;

	err = misc_register(&rdc321x_wdt_misc);
	if (err < 0) {
		dev_err(&pdev->dev, "misc_register failed\n");
		return err;
	}

	spin_lock_init(&rdc321x_wdt_device.lock);

	/*                    */
	pci_write_config_dword(rdc321x_wdt_device.sb_pdev,
				rdc321x_wdt_device.base_reg, RDC_WDT_RST);

	init_completion(&rdc321x_wdt_device.stop);
	rdc321x_wdt_device.queue = 0;

	clear_bit(0, &rdc321x_wdt_device.inuse);

	setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0);

	rdc321x_wdt_device.default_ticks = ticks;

	dev_info(&pdev->dev, "watchdog init success\n");

	return 0;
}

static int __devexit rdc321x_wdt_remove(struct platform_device *pdev)
{
	if (rdc321x_wdt_device.queue) {
		rdc321x_wdt_device.queue = 0;
		wait_for_completion(&rdc321x_wdt_device.stop);
	}

	misc_deregister(&rdc321x_wdt_misc);

	return 0;
}

static struct platform_driver rdc321x_wdt_driver = {
	.probe = rdc321x_wdt_probe,
	.remove = __devexit_p(rdc321x_wdt_remove),
	.driver = {
		.owner = THIS_MODULE,
		.name = "rdc321x-wdt",
	},
};

module_platform_driver(rdc321x_wdt_driver);

MODULE_AUTHOR("Florian Fainelli <*****@*****.**>");
MODULE_DESCRIPTION("RDC321x watchdog driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
Beispiel #9
0
static int
mxc_wdt_ioctl(struct inode *inode, struct file *file,
	      unsigned int cmd, unsigned long arg)
{
	int new_margin;
	int bootr;

	static struct watchdog_info ident = {
		.identity = "MXC Watchdog",
		.options = WDIOF_SETTIMEOUT,
		.firmware_version = 0,
	};

	switch (cmd) {
	default:
		return -ENOIOCTLCMD;
	case WDIOC_GETSUPPORT:
		return copy_to_user((struct watchdog_info __user *)arg, &ident,
				    sizeof(ident));
	case WDIOC_GETSTATUS:
		return put_user(0, (int __user *)arg);
	case WDIOC_GETBOOTSTATUS:
		bootr = mxc_wdt_get_bootreason(wdt_base_reg);
		return put_user(bootr, (int __user *)arg);
	case WDIOC_KEEPALIVE:
		mxc_wdt_ping(wdt_base_reg);
		return 0;
	case WDIOC_SETTIMEOUT:
		if (get_user(new_margin, (int __user *)arg))
			return -EFAULT;

		mxc_wdt_adjust_timeout(new_margin);
		mxc_wdt_disable(wdt_base_reg);
		mxc_wdt_set_timeout(wdt_base_reg);
		mxc_wdt_enable(wdt_base_reg);
		mxc_wdt_ping(wdt_base_reg);
		return 0;

	case WDIOC_GETTIMEOUT:
		mxc_wdt_ping(wdt_base_reg);
		new_margin = mxc_wdt_get_timeout(wdt_base_reg);
		return put_user(new_margin, (int __user *)arg);
	}
}

static struct file_operations mxc_wdt_fops = {
	.owner = THIS_MODULE,
	.write = mxc_wdt_write,
	.ioctl = mxc_wdt_ioctl,
	.open = mxc_wdt_open,
	.release = mxc_wdt_release,
};

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

static int __init mxc_wdt_probe(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct resource *res, *mem;
	int ret;

	/* reserve static register mappings */
	res = platform_get_resource(pdev, IORESOURCE_MEM, dev_num);
	if (!res)
		return -ENOENT;

	mem = request_mem_region(res->start, res->end - res->start + 1,
				 pdev->name);
	if (mem == NULL)
		return -EBUSY;

	dev_set_drvdata(dev, mem);

	wdt_base_reg = IO_ADDRESS(res->start);
	mxc_wdt_disable(wdt_base_reg);
	mxc_wdt_adjust_timeout(timer_margin);

	mxc_wdt_users = 0;

	mxc_wdt_miscdev.dev = dev;

	ret = misc_register(&mxc_wdt_miscdev);
	if (ret)
		goto fail;

	pr_info("MXC Watchdog # %d Timer: initial timeout %d sec\n", dev_num,
		timer_margin);

	return 0;

      fail:
	release_resource(mem);
	pr_info("MXC Watchdog Probe failed\n");
	return ret;
}

static void mxc_wdt_shutdown(struct device *dev)
{
	struct resource *res = dev_get_drvdata(dev);
	mxc_wdt_disable(res->start);
	pr_info("MXC Watchdog # %d shutdown\n", dev_num);
}

static int __exit mxc_wdt_remove(struct device *dev)
{
	struct resource *mem = dev_get_drvdata(dev);
	misc_deregister(&mxc_wdt_miscdev);
	release_resource(mem);
	pr_info("MXC Watchdog # %d removed\n", dev_num);
	return 0;
}

#ifdef	CONFIG_PM

/* REVISIT ... not clear this is the best way to handle system suspend; and
 * it's very inappropriate for selective device suspend (e.g. suspending this
 * through sysfs rather than by stopping the watchdog daemon).  Also, this
 * may not play well enough with NOWAYOUT...
 */

static int mxc_wdt_suspend(struct device *dev, u32 state, u32 level)
{
	struct resource *res = dev_get_drvdata(dev);
	if (level == SUSPEND_POWER_DOWN && mxc_wdt_users)
		mxc_wdt_disable(res->start);
	return 0;
}

static int mxc_wdt_resume(struct device *dev, u32 level)
{
	struct resource *res = dev_get_drvdata(dev);
	if (level == RESUME_POWER_ON && mxc_wdt_users) {
		mxc_wdt_enable(res->start);
		mxc_wdt_ping(res->start);
	}
	return 0;
}

#else
#define	mxc_wdt_suspend	NULL
#define	mxc_wdt_resume		NULL
#endif

static struct device_driver mxc_wdt_driver = {
	.name = "mxc_wdt",
	.bus = &platform_bus_type,
	.probe = mxc_wdt_probe,
	.shutdown = mxc_wdt_shutdown,
	.remove = __exit_p(mxc_wdt_remove),
	.suspend = mxc_wdt_suspend,
	.resume = mxc_wdt_resume,
};

static int __init mxc_wdt_init(void)
{
	pr_info("MXC WatchDog Driver %s\n", DVR_VER);

	if ((timer_margin < TIMER_MARGIN_MIN) ||
	    (timer_margin > TIMER_MARGIN_MAX)) {
		pr_info("MXC watchdog error. wrong timer_margin %d\n",
			timer_margin);
		pr_info("    Range: %d to %d seconds\n", TIMER_MARGIN_MIN,
			TIMER_MARGIN_MAX);
		return -EINVAL;
	}

	return driver_register(&mxc_wdt_driver);
}

static void __exit mxc_wdt_exit(void)
{
	driver_unregister(&mxc_wdt_driver);
	pr_info("MXC WatchDog Driver removed\n");
}

module_init(mxc_wdt_init);
module_exit(mxc_wdt_exit);

MODULE_AUTHOR("Freescale Semiconductor, Inc.");
MODULE_LICENSE("GPL");
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);