linux/drivers/watchdog/diag288_wdt.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Watchdog driver for z/VM and LPAR using the diag 288 interface.
   4 *
   5 * Under z/VM, expiration of the watchdog will send a "system restart" command
   6 * to CP.
   7 *
   8 * The command can be altered using the module parameter "cmd". This is
   9 * not recommended because it's only supported on z/VM but not whith LPAR.
  10 *
  11 * On LPAR, the watchdog will always trigger a system restart. the module
  12 * paramter cmd is meaningless here.
  13 *
  14 *
  15 * Copyright IBM Corp. 2004, 2013
  16 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
  17 *            Philipp Hachtmann (phacht@de.ibm.com)
  18 *
  19 */
  20
  21#define KMSG_COMPONENT "diag288_wdt"
  22#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  23
  24#include <linux/init.h>
  25#include <linux/kernel.h>
  26#include <linux/module.h>
  27#include <linux/moduleparam.h>
  28#include <linux/slab.h>
  29#include <linux/watchdog.h>
  30#include <linux/suspend.h>
  31#include <asm/ebcdic.h>
  32#include <asm/diag.h>
  33#include <linux/io.h>
  34
  35#define MAX_CMDLEN 240
  36#define DEFAULT_CMD "SYSTEM RESTART"
  37
  38#define MIN_INTERVAL 15     /* Minimal time supported by diag88 */
  39#define MAX_INTERVAL 3600   /* One hour should be enough - pure estimation */
  40
  41#define WDT_DEFAULT_TIMEOUT 30
  42
  43/* Function codes - init, change, cancel */
  44#define WDT_FUNC_INIT 0
  45#define WDT_FUNC_CHANGE 1
  46#define WDT_FUNC_CANCEL 2
  47#define WDT_FUNC_CONCEAL 0x80000000
  48
  49/* Action codes for LPAR watchdog */
  50#define LPARWDT_RESTART 0
  51
  52static char wdt_cmd[MAX_CMDLEN] = DEFAULT_CMD;
  53static bool conceal_on;
  54static bool nowayout_info = WATCHDOG_NOWAYOUT;
  55
  56MODULE_LICENSE("GPL");
  57MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
  58MODULE_AUTHOR("Philipp Hachtmann <phacht@de.ibm.com>");
  59
  60MODULE_DESCRIPTION("System z diag288  Watchdog Timer");
  61
  62module_param_string(cmd, wdt_cmd, MAX_CMDLEN, 0644);
  63MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers (z/VM only)");
  64
  65module_param_named(conceal, conceal_on, bool, 0644);
  66MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog is active (z/VM only)");
  67
  68module_param_named(nowayout, nowayout_info, bool, 0444);
  69MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = CONFIG_WATCHDOG_NOWAYOUT)");
  70
  71MODULE_ALIAS("vmwatchdog");
  72
  73static int __diag288(unsigned int func, unsigned int timeout,
  74                     unsigned long action, unsigned int len)
  75{
  76        register unsigned long __func asm("2") = func;
  77        register unsigned long __timeout asm("3") = timeout;
  78        register unsigned long __action asm("4") = action;
  79        register unsigned long __len asm("5") = len;
  80        int err;
  81
  82        err = -EINVAL;
  83        asm volatile(
  84                "       diag    %1, %3, 0x288\n"
  85                "0:     la      %0, 0\n"
  86                "1:\n"
  87                EX_TABLE(0b, 1b)
  88                : "+d" (err) : "d"(__func), "d"(__timeout),
  89                  "d"(__action), "d"(__len) : "1", "cc");
  90        return err;
  91}
  92
  93static int __diag288_vm(unsigned int  func, unsigned int timeout,
  94                        char *cmd, size_t len)
  95{
  96        diag_stat_inc(DIAG_STAT_X288);
  97        return __diag288(func, timeout, virt_to_phys(cmd), len);
  98}
  99
 100static int __diag288_lpar(unsigned int func, unsigned int timeout,
 101                          unsigned long action)
 102{
 103        diag_stat_inc(DIAG_STAT_X288);
 104        return __diag288(func, timeout, action, 0);
 105}
 106
 107static unsigned long wdt_status;
 108
 109#define DIAG_WDOG_BUSY  0
 110
 111static int wdt_start(struct watchdog_device *dev)
 112{
 113        char *ebc_cmd;
 114        size_t len;
 115        int ret;
 116        unsigned int func;
 117
 118        if (test_and_set_bit(DIAG_WDOG_BUSY, &wdt_status))
 119                return -EBUSY;
 120
 121        if (MACHINE_IS_VM) {
 122                ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
 123                if (!ebc_cmd) {
 124                        clear_bit(DIAG_WDOG_BUSY, &wdt_status);
 125                        return -ENOMEM;
 126                }
 127                len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
 128                ASCEBC(ebc_cmd, MAX_CMDLEN);
 129                EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
 130
 131                func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
 132                        : WDT_FUNC_INIT;
 133                ret = __diag288_vm(func, dev->timeout, ebc_cmd, len);
 134                WARN_ON(ret != 0);
 135                kfree(ebc_cmd);
 136        } else {
 137                ret = __diag288_lpar(WDT_FUNC_INIT,
 138                                     dev->timeout, LPARWDT_RESTART);
 139        }
 140
 141        if (ret) {
 142                pr_err("The watchdog cannot be activated\n");
 143                clear_bit(DIAG_WDOG_BUSY, &wdt_status);
 144                return ret;
 145        }
 146        return 0;
 147}
 148
 149static int wdt_stop(struct watchdog_device *dev)
 150{
 151        int ret;
 152
 153        diag_stat_inc(DIAG_STAT_X288);
 154        ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0);
 155
 156        clear_bit(DIAG_WDOG_BUSY, &wdt_status);
 157
 158        return ret;
 159}
 160
 161static int wdt_ping(struct watchdog_device *dev)
 162{
 163        char *ebc_cmd;
 164        size_t len;
 165        int ret;
 166        unsigned int func;
 167
 168        if (MACHINE_IS_VM) {
 169                ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
 170                if (!ebc_cmd)
 171                        return -ENOMEM;
 172                len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
 173                ASCEBC(ebc_cmd, MAX_CMDLEN);
 174                EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
 175
 176                /*
 177                 * It seems to be ok to z/VM to use the init function to
 178                 * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must
 179                 * be used when the watchdog is running.
 180                 */
 181                func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
 182                        : WDT_FUNC_INIT;
 183
 184                ret = __diag288_vm(func, dev->timeout, ebc_cmd, len);
 185                WARN_ON(ret != 0);
 186                kfree(ebc_cmd);
 187        } else {
 188                ret = __diag288_lpar(WDT_FUNC_CHANGE, dev->timeout, 0);
 189        }
 190
 191        if (ret)
 192                pr_err("The watchdog timer cannot be started or reset\n");
 193        return ret;
 194}
 195
 196static int wdt_set_timeout(struct watchdog_device * dev, unsigned int new_to)
 197{
 198        dev->timeout = new_to;
 199        return wdt_ping(dev);
 200}
 201
 202static const struct watchdog_ops wdt_ops = {
 203        .owner = THIS_MODULE,
 204        .start = wdt_start,
 205        .stop = wdt_stop,
 206        .ping = wdt_ping,
 207        .set_timeout = wdt_set_timeout,
 208};
 209
 210static const struct watchdog_info wdt_info = {
 211        .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
 212        .firmware_version = 0,
 213        .identity = "z Watchdog",
 214};
 215
 216static struct watchdog_device wdt_dev = {
 217        .parent = NULL,
 218        .info = &wdt_info,
 219        .ops = &wdt_ops,
 220        .bootstatus = 0,
 221        .timeout = WDT_DEFAULT_TIMEOUT,
 222        .min_timeout = MIN_INTERVAL,
 223        .max_timeout = MAX_INTERVAL,
 224};
 225
 226/*
 227 * It makes no sense to go into suspend while the watchdog is running.
 228 * Depending on the memory size, the watchdog might trigger, while we
 229 * are still saving the memory.
 230 */
 231static int wdt_suspend(void)
 232{
 233        if (test_and_set_bit(DIAG_WDOG_BUSY, &wdt_status)) {
 234                pr_err("Linux cannot be suspended while the watchdog is in use\n");
 235                return notifier_from_errno(-EBUSY);
 236        }
 237        return NOTIFY_DONE;
 238}
 239
 240static int wdt_resume(void)
 241{
 242        clear_bit(DIAG_WDOG_BUSY, &wdt_status);
 243        return NOTIFY_DONE;
 244}
 245
 246static int wdt_power_event(struct notifier_block *this, unsigned long event,
 247                           void *ptr)
 248{
 249        switch (event) {
 250        case PM_POST_HIBERNATION:
 251        case PM_POST_SUSPEND:
 252                return wdt_resume();
 253        case PM_HIBERNATION_PREPARE:
 254        case PM_SUSPEND_PREPARE:
 255                return wdt_suspend();
 256        default:
 257                return NOTIFY_DONE;
 258        }
 259}
 260
 261static struct notifier_block wdt_power_notifier = {
 262        .notifier_call = wdt_power_event,
 263};
 264
 265static int __init diag288_init(void)
 266{
 267        int ret;
 268        char ebc_begin[] = {
 269                194, 197, 199, 201, 213
 270        };
 271
 272        watchdog_set_nowayout(&wdt_dev, nowayout_info);
 273
 274        if (MACHINE_IS_VM) {
 275                if (__diag288_vm(WDT_FUNC_INIT, 15,
 276                                 ebc_begin, sizeof(ebc_begin)) != 0) {
 277                        pr_err("The watchdog cannot be initialized\n");
 278                        return -EINVAL;
 279                }
 280        } else {
 281                if (__diag288_lpar(WDT_FUNC_INIT, 30, LPARWDT_RESTART)) {
 282                        pr_err("The watchdog cannot be initialized\n");
 283                        return -EINVAL;
 284                }
 285        }
 286
 287        if (__diag288_lpar(WDT_FUNC_CANCEL, 0, 0)) {
 288                pr_err("The watchdog cannot be deactivated\n");
 289                return -EINVAL;
 290        }
 291
 292        ret = register_pm_notifier(&wdt_power_notifier);
 293        if (ret)
 294                return ret;
 295
 296        ret = watchdog_register_device(&wdt_dev);
 297        if (ret)
 298                unregister_pm_notifier(&wdt_power_notifier);
 299
 300        return ret;
 301}
 302
 303static void __exit diag288_exit(void)
 304{
 305        watchdog_unregister_device(&wdt_dev);
 306        unregister_pm_notifier(&wdt_power_notifier);
 307}
 308
 309module_init(diag288_init);
 310module_exit(diag288_exit);
 311