/*
 * Watchdog driver for z/VM and LPAR using the diag 288 interface.
 *
 * Under z/VM, expiration of the watchdog will send a "system restart" command
 * to CP.
 *
 * The command can be altered using the module parameter "cmd". This is
 * not recommended because it's only supported on z/VM but not whith LPAR.
 *
 * On LPAR, the watchdog will always trigger a system restart. the module
 * paramter cmd is meaningless here.
 *
 *
 * Copyright IBM Corp. 2004, 2013
 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
 *	      Philipp Hachtmann (phacht@de.ibm.com)
 *
 */

#define KMSG_COMPONENT "diag288_wdt"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/watchdog.h>
#include <linux/suspend.h>
#include <asm/ebcdic.h>
#include <linux/io.h>
#include <linux/uaccess.h>

#define MAX_CMDLEN 240
#define DEFAULT_CMD "SYSTEM RESTART"

#define MIN_INTERVAL 15     /* Minimal time supported by diag88 */
#define MAX_INTERVAL 3600   /* One hour should be enough - pure estimation */

#define WDT_DEFAULT_TIMEOUT 30

/* Function codes - init, change, cancel */
#define WDT_FUNC_INIT 0
#define WDT_FUNC_CHANGE 1
#define WDT_FUNC_CANCEL 2
#define WDT_FUNC_CONCEAL 0x80000000

/* Action codes for LPAR watchdog */
#define LPARWDT_RESTART 0

static char wdt_cmd[MAX_CMDLEN] = DEFAULT_CMD;
static bool conceal_on;
static bool nowayout_info = WATCHDOG_NOWAYOUT;

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
MODULE_AUTHOR("Philipp Hachtmann <phacht@de.ibm.com>");

MODULE_DESCRIPTION("System z diag288  Watchdog Timer");

module_param_string(cmd, wdt_cmd, MAX_CMDLEN, 0644);
MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers (z/VM only)");

module_param_named(conceal, conceal_on, bool, 0644);
MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog is active (z/VM only)");

module_param_named(nowayout, nowayout_info, bool, 0444);
MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = CONFIG_WATCHDOG_NOWAYOUT)");

MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
MODULE_ALIAS("vmwatchdog");

static int __diag288(unsigned int func, unsigned int timeout,
		     unsigned long action, unsigned int len)
{
	register unsigned long __func asm("2") = func;
	register unsigned long __timeout asm("3") = timeout;
	register unsigned long __action asm("4") = action;
	register unsigned long __len asm("5") = len;
	int err;

	err = -EINVAL;
	asm volatile(
		"	diag	%1, %3, 0x288\n"
		"0:	la	%0, 0\n"
		"1:\n"
		EX_TABLE(0b, 1b)
		: "+d" (err) : "d"(__func), "d"(__timeout),
		  "d"(__action), "d"(__len) : "1", "cc");
	return err;
}

static int __diag288_vm(unsigned int  func, unsigned int timeout,
			char *cmd, size_t len)
{
	return __diag288(func, timeout, virt_to_phys(cmd), len);
}

static int __diag288_lpar(unsigned int func, unsigned int timeout,
			  unsigned long action)
{
	return __diag288(func, timeout, action, 0);
}

static int wdt_start(struct watchdog_device *dev)
{
	char *ebc_cmd;
	size_t len;
	int ret;
	unsigned int func;

	ret = -ENODEV;

	if (MACHINE_IS_VM) {
		ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
		if (!ebc_cmd)
			return -ENOMEM;
		len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
		ASCEBC(ebc_cmd, MAX_CMDLEN);
		EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);

		func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
			: WDT_FUNC_INIT;
		ret = __diag288_vm(func, dev->timeout, ebc_cmd, len);
		WARN_ON(ret != 0);
		kfree(ebc_cmd);
	} else {
		ret = __diag288_lpar(WDT_FUNC_INIT,
				     dev->timeout, LPARWDT_RESTART);
	}

	if (ret) {
		pr_err("The watchdog cannot be activated\n");
		return ret;
	}
	return 0;
}

static int wdt_stop(struct watchdog_device *dev)
{
	int ret;

	ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0);
	return ret;
}

static int wdt_ping(struct watchdog_device *dev)
{
	char *ebc_cmd;
	size_t len;
	int ret;
	unsigned int func;

	ret = -ENODEV;

	if (MACHINE_IS_VM) {
		ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
		if (!ebc_cmd)
			return -ENOMEM;
		len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
		ASCEBC(ebc_cmd, MAX_CMDLEN);
		EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);

		/*
		 * It seems to be ok to z/VM to use the init function to
		 * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must
		 * be used when the watchdog is running.
		 */
		func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
			: WDT_FUNC_INIT;

		ret = __diag288_vm(func, dev->timeout, ebc_cmd, len);
		WARN_ON(ret != 0);
		kfree(ebc_cmd);
	} else {
		ret = __diag288_lpar(WDT_FUNC_CHANGE, dev->timeout, 0);
	}

	if (ret)
		pr_err("The watchdog timer cannot be started or reset\n");
	return ret;
}

static int wdt_set_timeout(struct watchdog_device * dev, unsigned int new_to)
{
	dev->timeout = new_to;
	return wdt_ping(dev);
}

static struct watchdog_ops wdt_ops = {
	.owner = THIS_MODULE,
	.start = wdt_start,
	.stop = wdt_stop,
	.ping = wdt_ping,
	.set_timeout = wdt_set_timeout,
};

static struct watchdog_info wdt_info = {
	.options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
	.firmware_version = 0,
	.identity = "z Watchdog",
};

static struct watchdog_device wdt_dev = {
	.parent = NULL,
	.info = &wdt_info,
	.ops = &wdt_ops,
	.bootstatus = 0,
	.timeout = WDT_DEFAULT_TIMEOUT,
	.min_timeout = MIN_INTERVAL,
	.max_timeout = MAX_INTERVAL,
};

/*
 * It makes no sense to go into suspend while the watchdog is running.
 * Depending on the memory size, the watchdog might trigger, while we
 * are still saving the memory.
 * We reuse the open flag to ensure that suspend and watchdog open are
 * exclusive operations
 */
static int wdt_suspend(void)
{
	if (test_and_set_bit(WDOG_DEV_OPEN, &wdt_dev.status)) {
		pr_err("Linux cannot be suspended while the watchdog is in use\n");
		return notifier_from_errno(-EBUSY);
	}
	if (test_bit(WDOG_ACTIVE, &wdt_dev.status)) {
		clear_bit(WDOG_DEV_OPEN, &wdt_dev.status);
		pr_err("Linux cannot be suspended while the watchdog is in use\n");
		return notifier_from_errno(-EBUSY);
	}
	return NOTIFY_DONE;
}

static int wdt_resume(void)
{
	clear_bit(WDOG_DEV_OPEN, &wdt_dev.status);
	return NOTIFY_DONE;
}

static int wdt_power_event(struct notifier_block *this, unsigned long event,
			   void *ptr)
{
	switch (event) {
	case PM_POST_HIBERNATION:
	case PM_POST_SUSPEND:
		return wdt_resume();
	case PM_HIBERNATION_PREPARE:
	case PM_SUSPEND_PREPARE:
		return wdt_suspend();
	default:
		return NOTIFY_DONE;
	}
}

static struct notifier_block wdt_power_notifier = {
	.notifier_call = wdt_power_event,
};

static int __init diag288_init(void)
{
	int ret;
	char ebc_begin[] = {
		194, 197, 199, 201, 213
	};

	watchdog_set_nowayout(&wdt_dev, nowayout_info);

	if (MACHINE_IS_VM) {
		if (__diag288_vm(WDT_FUNC_INIT, 15,
				 ebc_begin, sizeof(ebc_begin)) != 0) {
			pr_err("The watchdog cannot be initialized\n");
			return -EINVAL;
		}
	} else {
		if (__diag288_lpar(WDT_FUNC_INIT, 30, LPARWDT_RESTART)) {
			pr_err("The watchdog cannot be initialized\n");
			return -EINVAL;
		}
	}

	if (__diag288_lpar(WDT_FUNC_CANCEL, 0, 0)) {
		pr_err("The watchdog cannot be deactivated\n");
		return -EINVAL;
	}

	ret = register_pm_notifier(&wdt_power_notifier);
	if (ret)
		return ret;

	ret = watchdog_register_device(&wdt_dev);
	if (ret)
		unregister_pm_notifier(&wdt_power_notifier);

	return ret;
}

static void __exit diag288_exit(void)
{
	watchdog_unregister_device(&wdt_dev);
	unregister_pm_notifier(&wdt_power_notifier);
}

module_init(diag288_init);
module_exit(diag288_exit);
