1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (c) 2022 International Business Machines, Inc. 4 */ 5 6 #include <linux/bitops.h> 7 #include <linux/kernel.h> 8 #include <linux/limits.h> 9 #include <linux/math.h> 10 #include <linux/module.h> 11 #include <linux/moduleparam.h> 12 #include <linux/platform_device.h> 13 #include <linux/time64.h> 14 #include <linux/watchdog.h> 15 16 #define DRV_NAME "pseries-wdt" 17 18 /* 19 * H_WATCHDOG Input 20 * 21 * R4: "flags": 22 * 23 * Bits 48-55: "operation" 24 */ 25 #define PSERIES_WDTF_OP_START 0x100UL /* start timer */ 26 #define PSERIES_WDTF_OP_STOP 0x200UL /* stop timer */ 27 #define PSERIES_WDTF_OP_QUERY 0x300UL /* query timer capabilities */ 28 29 /* 30 * Bits 56-63: "timeoutAction" (for "Start Watchdog" only) 31 */ 32 #define PSERIES_WDTF_ACTION_HARD_POWEROFF 0x1UL /* poweroff */ 33 #define PSERIES_WDTF_ACTION_HARD_RESTART 0x2UL /* restart */ 34 #define PSERIES_WDTF_ACTION_DUMP_RESTART 0x3UL /* dump + restart */ 35 36 /* 37 * H_WATCHDOG Output 38 * 39 * R3: Return code 40 * 41 * H_SUCCESS The operation completed. 42 * 43 * H_BUSY The hypervisor is too busy; retry the operation. 44 * 45 * H_PARAMETER The given "flags" are somehow invalid. Either the 46 * "operation" or "timeoutAction" is invalid, or a 47 * reserved bit is set. 48 * 49 * H_P2 The given "watchdogNumber" is zero or exceeds the 50 * supported maximum value. 51 * 52 * H_P3 The given "timeoutInMs" is below the supported 53 * minimum value. 54 * 55 * H_NOOP The given "watchdogNumber" is already stopped. 56 * 57 * H_HARDWARE The operation failed for ineffable reasons. 58 * 59 * H_FUNCTION The H_WATCHDOG hypercall is not supported by this 60 * hypervisor. 61 * 62 * R4: 63 * 64 * - For the "Query Watchdog Capabilities" operation, a 64-bit 65 * structure: 66 */ 67 #define PSERIES_WDTQ_MIN_TIMEOUT(cap) (((cap) >> 48) & 0xffff) 68 #define PSERIES_WDTQ_MAX_NUMBER(cap) (((cap) >> 32) & 0xffff) 69 70 static const unsigned long pseries_wdt_action[] = { 71 [0] = PSERIES_WDTF_ACTION_HARD_POWEROFF, 72 [1] = PSERIES_WDTF_ACTION_HARD_RESTART, 73 [2] = PSERIES_WDTF_ACTION_DUMP_RESTART, 74 }; 75 76 #define WATCHDOG_ACTION 1 77 static unsigned int action = WATCHDOG_ACTION; 78 module_param(action, uint, 0444); 79 MODULE_PARM_DESC(action, "Action taken when watchdog expires (default=" 80 __MODULE_STRING(WATCHDOG_ACTION) ")"); 81 82 static bool nowayout = WATCHDOG_NOWAYOUT; 83 module_param(nowayout, bool, 0444); 84 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" 85 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); 86 87 #define WATCHDOG_TIMEOUT 60 88 static unsigned int timeout = WATCHDOG_TIMEOUT; 89 module_param(timeout, uint, 0444); 90 MODULE_PARM_DESC(timeout, "Initial watchdog timeout in seconds (default=" 91 __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 92 93 struct pseries_wdt { 94 struct watchdog_device wd; 95 unsigned long action; 96 unsigned long num; /* Watchdog numbers are 1-based */ 97 }; 98 99 static int pseries_wdt_start(struct watchdog_device *wdd) 100 { 101 struct pseries_wdt *pw = watchdog_get_drvdata(wdd); 102 struct device *dev = wdd->parent; 103 unsigned long flags, msecs; 104 long rc; 105 106 flags = pw->action | PSERIES_WDTF_OP_START; 107 msecs = wdd->timeout * MSEC_PER_SEC; 108 rc = plpar_hcall_norets(H_WATCHDOG, flags, pw->num, msecs); 109 if (rc != H_SUCCESS) { 110 dev_crit(dev, "H_WATCHDOG: %ld: failed to start timer %lu", 111 rc, pw->num); 112 return -EIO; 113 } 114 return 0; 115 } 116 117 static int pseries_wdt_stop(struct watchdog_device *wdd) 118 { 119 struct pseries_wdt *pw = watchdog_get_drvdata(wdd); 120 struct device *dev = wdd->parent; 121 long rc; 122 123 rc = plpar_hcall_norets(H_WATCHDOG, PSERIES_WDTF_OP_STOP, pw->num); 124 if (rc != H_SUCCESS && rc != H_NOOP) { 125 dev_crit(dev, "H_WATCHDOG: %ld: failed to stop timer %lu", 126 rc, pw->num); 127 return -EIO; 128 } 129 return 0; 130 } 131 132 static struct watchdog_info pseries_wdt_info = { 133 .identity = DRV_NAME, 134 .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT 135 | WDIOF_PRETIMEOUT, 136 }; 137 138 static const struct watchdog_ops pseries_wdt_ops = { 139 .owner = THIS_MODULE, 140 .start = pseries_wdt_start, 141 .stop = pseries_wdt_stop, 142 }; 143 144 static int pseries_wdt_probe(struct platform_device *pdev) 145 { 146 unsigned long ret[PLPAR_HCALL_BUFSIZE] = { 0 }; 147 struct pseries_wdt *pw; 148 unsigned long cap; 149 long msecs, rc; 150 int err; 151 152 rc = plpar_hcall(H_WATCHDOG, ret, PSERIES_WDTF_OP_QUERY); 153 if (rc == H_FUNCTION) 154 return -ENODEV; 155 if (rc != H_SUCCESS) 156 return -EIO; 157 cap = ret[0]; 158 159 pw = devm_kzalloc(&pdev->dev, sizeof(*pw), GFP_KERNEL); 160 if (!pw) 161 return -ENOMEM; 162 163 /* 164 * Assume watchdogNumber 1 for now. If we ever support 165 * multiple timers we will need to devise a way to choose a 166 * distinct watchdogNumber for each platform device at device 167 * registration time. 168 */ 169 pw->num = 1; 170 if (PSERIES_WDTQ_MAX_NUMBER(cap) < pw->num) 171 return -ENODEV; 172 173 if (action >= ARRAY_SIZE(pseries_wdt_action)) 174 return -EINVAL; 175 pw->action = pseries_wdt_action[action]; 176 177 pw->wd.parent = &pdev->dev; 178 pw->wd.info = &pseries_wdt_info; 179 pw->wd.ops = &pseries_wdt_ops; 180 msecs = PSERIES_WDTQ_MIN_TIMEOUT(cap); 181 pw->wd.min_timeout = DIV_ROUND_UP(msecs, MSEC_PER_SEC); 182 pw->wd.max_timeout = UINT_MAX / 1000; /* from linux/watchdog.h */ 183 pw->wd.timeout = timeout; 184 if (watchdog_init_timeout(&pw->wd, 0, NULL)) 185 return -EINVAL; 186 watchdog_set_nowayout(&pw->wd, nowayout); 187 watchdog_stop_on_reboot(&pw->wd); 188 watchdog_stop_on_unregister(&pw->wd); 189 watchdog_set_drvdata(&pw->wd, pw); 190 191 err = devm_watchdog_register_device(&pdev->dev, &pw->wd); 192 if (err) 193 return err; 194 195 platform_set_drvdata(pdev, &pw->wd); 196 197 return 0; 198 } 199 200 static int pseries_wdt_suspend(struct platform_device *pdev, pm_message_t state) 201 { 202 struct watchdog_device *wd = platform_get_drvdata(pdev); 203 204 if (watchdog_active(wd)) 205 return pseries_wdt_stop(wd); 206 return 0; 207 } 208 209 static int pseries_wdt_resume(struct platform_device *pdev) 210 { 211 struct watchdog_device *wd = platform_get_drvdata(pdev); 212 213 if (watchdog_active(wd)) 214 return pseries_wdt_start(wd); 215 return 0; 216 } 217 218 static const struct platform_device_id pseries_wdt_id[] = { 219 { .name = "pseries-wdt" }, 220 {} 221 }; 222 MODULE_DEVICE_TABLE(platform, pseries_wdt_id); 223 224 static struct platform_driver pseries_wdt_driver = { 225 .driver = { 226 .name = DRV_NAME, 227 }, 228 .id_table = pseries_wdt_id, 229 .probe = pseries_wdt_probe, 230 .resume = pseries_wdt_resume, 231 .suspend = pseries_wdt_suspend, 232 }; 233 module_platform_driver(pseries_wdt_driver); 234 235 MODULE_AUTHOR("Alexey Kardashevskiy"); 236 MODULE_AUTHOR("Scott Cheloha"); 237 MODULE_DESCRIPTION("POWER Architecture Platform Watchdog Driver"); 238 MODULE_LICENSE("GPL"); 239