0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0017
0018 #include <linux/fs.h>
0019 #include <linux/init.h>
0020 #include <linux/kernel.h>
0021 #include <linux/miscdevice.h>
0022 #include <linux/module.h>
0023 #include <linux/notifier.h>
0024 #include <linux/reboot.h>
0025 #include <linux/types.h>
0026 #include <linux/watchdog.h>
0027 #include <linux/uaccess.h>
0028
0029 #include <asm/rtas.h>
0030
0031 #define WDRTAS_MAGIC_CHAR 42
0032 #define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \
0033 WDIOF_MAGICCLOSE)
0034
0035 MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
0036 MODULE_DESCRIPTION("RTAS watchdog driver");
0037 MODULE_LICENSE("GPL");
0038
0039 static bool wdrtas_nowayout = WATCHDOG_NOWAYOUT;
0040 static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
0041 static char wdrtas_expect_close;
0042
0043 static int wdrtas_interval;
0044
0045 #define WDRTAS_THERMAL_SENSOR 3
0046 static int wdrtas_token_get_sensor_state;
0047 #define WDRTAS_SURVEILLANCE_IND 9000
0048 static int wdrtas_token_set_indicator;
0049 #define WDRTAS_SP_SPI 28
0050 static int wdrtas_token_get_sp;
0051 static int wdrtas_token_event_scan;
0052
0053 #define WDRTAS_DEFAULT_INTERVAL 300
0054
0055 #define WDRTAS_LOGBUFFER_LEN 128
0056 static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 static int wdrtas_set_interval(int interval)
0073 {
0074 long result;
0075 static int print_msg = 10;
0076
0077
0078 interval = (interval + 59) / 60;
0079
0080 result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
0081 WDRTAS_SURVEILLANCE_IND, 0, interval);
0082 if (result < 0 && print_msg) {
0083 pr_err("setting the watchdog to %i timeout failed: %li\n",
0084 interval, result);
0085 print_msg--;
0086 }
0087
0088 return result;
0089 }
0090
0091 #define WDRTAS_SP_SPI_LEN 4
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103 static int wdrtas_get_interval(int fallback_value)
0104 {
0105 long result;
0106 char value[WDRTAS_SP_SPI_LEN];
0107
0108 spin_lock(&rtas_data_buf_lock);
0109 memset(rtas_data_buf, 0, WDRTAS_SP_SPI_LEN);
0110 result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
0111 WDRTAS_SP_SPI, __pa(rtas_data_buf),
0112 WDRTAS_SP_SPI_LEN);
0113
0114 memcpy(value, rtas_data_buf, WDRTAS_SP_SPI_LEN);
0115 spin_unlock(&rtas_data_buf_lock);
0116
0117 if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) {
0118 pr_warn("could not get sp_spi watchdog timeout (%li). Continuing\n",
0119 result);
0120 return fallback_value;
0121 }
0122
0123
0124 return ((int)value[2]) * 60;
0125 }
0126
0127
0128
0129
0130
0131
0132
0133 static void wdrtas_timer_start(void)
0134 {
0135 wdrtas_set_interval(wdrtas_interval);
0136 }
0137
0138
0139
0140
0141
0142
0143
0144 static void wdrtas_timer_stop(void)
0145 {
0146 wdrtas_set_interval(0);
0147 }
0148
0149
0150
0151
0152
0153
0154
0155
0156 static void wdrtas_timer_keepalive(void)
0157 {
0158 long result;
0159
0160 do {
0161 result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
0162 RTAS_EVENT_SCAN_ALL_EVENTS, 0,
0163 (void *)__pa(wdrtas_logbuffer),
0164 WDRTAS_LOGBUFFER_LEN);
0165 if (result < 0)
0166 pr_err("event-scan failed: %li\n", result);
0167 if (result == 0)
0168 print_hex_dump(KERN_INFO, "dumping event, data: ",
0169 DUMP_PREFIX_OFFSET, 16, 1,
0170 wdrtas_logbuffer, WDRTAS_LOGBUFFER_LEN, false);
0171 } while (result == 0);
0172 }
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182 static int wdrtas_get_temperature(void)
0183 {
0184 int result;
0185 int temperature = 0;
0186
0187 result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature);
0188
0189 if (result < 0)
0190 pr_warn("reading the thermal sensor failed: %i\n", result);
0191 else
0192 temperature = ((temperature * 9) / 5) + 32;
0193
0194 return temperature;
0195 }
0196
0197
0198
0199
0200
0201
0202
0203 static int wdrtas_get_status(void)
0204 {
0205 return 0;
0206 }
0207
0208
0209
0210
0211
0212
0213
0214 static int wdrtas_get_boot_status(void)
0215 {
0216 return 0;
0217 }
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 static ssize_t wdrtas_write(struct file *file, const char __user *buf,
0235 size_t len, loff_t *ppos)
0236 {
0237 int i;
0238 char c;
0239
0240 if (!len)
0241 goto out;
0242
0243 if (!wdrtas_nowayout) {
0244 wdrtas_expect_close = 0;
0245
0246 for (i = 0; i < len; i++) {
0247 if (get_user(c, buf + i))
0248 return -EFAULT;
0249
0250 if (c == 'V')
0251 wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
0252 }
0253 }
0254
0255 wdrtas_timer_keepalive();
0256
0257 out:
0258 return len;
0259 }
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272 static long wdrtas_ioctl(struct file *file, unsigned int cmd,
0273 unsigned long arg)
0274 {
0275 int __user *argp = (void __user *)arg;
0276 int i;
0277 static const struct watchdog_info wdinfo = {
0278 .options = WDRTAS_SUPPORTED_MASK,
0279 .firmware_version = 0,
0280 .identity = "wdrtas",
0281 };
0282
0283 switch (cmd) {
0284 case WDIOC_GETSUPPORT:
0285 if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
0286 return -EFAULT;
0287 return 0;
0288
0289 case WDIOC_GETSTATUS:
0290 i = wdrtas_get_status();
0291 return put_user(i, argp);
0292
0293 case WDIOC_GETBOOTSTATUS:
0294 i = wdrtas_get_boot_status();
0295 return put_user(i, argp);
0296
0297 case WDIOC_GETTEMP:
0298 if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
0299 return -EOPNOTSUPP;
0300
0301 i = wdrtas_get_temperature();
0302 return put_user(i, argp);
0303
0304 case WDIOC_SETOPTIONS:
0305 if (get_user(i, argp))
0306 return -EFAULT;
0307 if (i & WDIOS_DISABLECARD)
0308 wdrtas_timer_stop();
0309 if (i & WDIOS_ENABLECARD) {
0310 wdrtas_timer_keepalive();
0311 wdrtas_timer_start();
0312 }
0313
0314
0315
0316 return 0;
0317
0318 case WDIOC_KEEPALIVE:
0319 wdrtas_timer_keepalive();
0320 return 0;
0321
0322 case WDIOC_SETTIMEOUT:
0323 if (get_user(i, argp))
0324 return -EFAULT;
0325
0326 if (wdrtas_set_interval(i))
0327 return -EINVAL;
0328
0329 wdrtas_timer_keepalive();
0330
0331 if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
0332 wdrtas_interval = i;
0333 else
0334 wdrtas_interval = wdrtas_get_interval(i);
0335 fallthrough;
0336
0337 case WDIOC_GETTIMEOUT:
0338 return put_user(wdrtas_interval, argp);
0339
0340 default:
0341 return -ENOTTY;
0342 }
0343 }
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355 static int wdrtas_open(struct inode *inode, struct file *file)
0356 {
0357
0358 if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
0359 atomic_dec(&wdrtas_miscdev_open);
0360 return -EBUSY;
0361 }
0362
0363 wdrtas_timer_start();
0364 wdrtas_timer_keepalive();
0365
0366 return stream_open(inode, file);
0367 }
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378 static int wdrtas_close(struct inode *inode, struct file *file)
0379 {
0380
0381 if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
0382 wdrtas_timer_stop();
0383 else {
0384 pr_warn("got unexpected close. Watchdog not stopped.\n");
0385 wdrtas_timer_keepalive();
0386 }
0387
0388 wdrtas_expect_close = 0;
0389 atomic_dec(&wdrtas_miscdev_open);
0390 return 0;
0391 }
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406 static ssize_t wdrtas_temp_read(struct file *file, char __user *buf,
0407 size_t count, loff_t *ppos)
0408 {
0409 int temperature = 0;
0410
0411 temperature = wdrtas_get_temperature();
0412 if (temperature < 0)
0413 return temperature;
0414
0415 if (copy_to_user(buf, &temperature, 1))
0416 return -EFAULT;
0417
0418 return 1;
0419 }
0420
0421
0422
0423
0424
0425
0426
0427
0428
0429
0430 static int wdrtas_temp_open(struct inode *inode, struct file *file)
0431 {
0432 return stream_open(inode, file);
0433 }
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444 static int wdrtas_temp_close(struct inode *inode, struct file *file)
0445 {
0446 return 0;
0447 }
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459 static int wdrtas_reboot(struct notifier_block *this,
0460 unsigned long code, void *ptr)
0461 {
0462 if (code == SYS_DOWN || code == SYS_HALT)
0463 wdrtas_timer_stop();
0464
0465 return NOTIFY_DONE;
0466 }
0467
0468
0469
0470 static const struct file_operations wdrtas_fops = {
0471 .owner = THIS_MODULE,
0472 .llseek = no_llseek,
0473 .write = wdrtas_write,
0474 .unlocked_ioctl = wdrtas_ioctl,
0475 .compat_ioctl = compat_ptr_ioctl,
0476 .open = wdrtas_open,
0477 .release = wdrtas_close,
0478 };
0479
0480 static struct miscdevice wdrtas_miscdev = {
0481 .minor = WATCHDOG_MINOR,
0482 .name = "watchdog",
0483 .fops = &wdrtas_fops,
0484 };
0485
0486 static const struct file_operations wdrtas_temp_fops = {
0487 .owner = THIS_MODULE,
0488 .llseek = no_llseek,
0489 .read = wdrtas_temp_read,
0490 .open = wdrtas_temp_open,
0491 .release = wdrtas_temp_close,
0492 };
0493
0494 static struct miscdevice wdrtas_tempdev = {
0495 .minor = TEMP_MINOR,
0496 .name = "temperature",
0497 .fops = &wdrtas_temp_fops,
0498 };
0499
0500 static struct notifier_block wdrtas_notifier = {
0501 .notifier_call = wdrtas_reboot,
0502 };
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513 static int wdrtas_get_tokens(void)
0514 {
0515 wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
0516 if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
0517 pr_warn("couldn't get token for get-sensor-state. Trying to continue without temperature support.\n");
0518 }
0519
0520 wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
0521 if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
0522 pr_warn("couldn't get token for ibm,get-system-parameter. Trying to continue with a default timeout value of %i seconds.\n",
0523 WDRTAS_DEFAULT_INTERVAL);
0524 }
0525
0526 wdrtas_token_set_indicator = rtas_token("set-indicator");
0527 if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
0528 pr_err("couldn't get token for set-indicator. Terminating watchdog code.\n");
0529 return -EIO;
0530 }
0531
0532 wdrtas_token_event_scan = rtas_token("event-scan");
0533 if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
0534 pr_err("couldn't get token for event-scan. Terminating watchdog code.\n");
0535 return -EIO;
0536 }
0537
0538 return 0;
0539 }
0540
0541
0542
0543
0544
0545
0546
0547 static void wdrtas_unregister_devs(void)
0548 {
0549 misc_deregister(&wdrtas_miscdev);
0550 if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
0551 misc_deregister(&wdrtas_tempdev);
0552 }
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562 static int wdrtas_register_devs(void)
0563 {
0564 int result;
0565
0566 result = misc_register(&wdrtas_miscdev);
0567 if (result) {
0568 pr_err("couldn't register watchdog misc device. Terminating watchdog code.\n");
0569 return result;
0570 }
0571
0572 if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
0573 result = misc_register(&wdrtas_tempdev);
0574 if (result) {
0575 pr_warn("couldn't register watchdog temperature misc device. Continuing without temperature support.\n");
0576 wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
0577 }
0578 }
0579
0580 return 0;
0581 }
0582
0583
0584
0585
0586
0587
0588
0589
0590 static int __init wdrtas_init(void)
0591 {
0592 if (wdrtas_get_tokens())
0593 return -ENODEV;
0594
0595 if (wdrtas_register_devs())
0596 return -ENODEV;
0597
0598 if (register_reboot_notifier(&wdrtas_notifier)) {
0599 pr_err("could not register reboot notifier. Terminating watchdog code.\n");
0600 wdrtas_unregister_devs();
0601 return -ENODEV;
0602 }
0603
0604 if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
0605 wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
0606 else
0607 wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
0608
0609 return 0;
0610 }
0611
0612
0613
0614
0615
0616
0617 static void __exit wdrtas_exit(void)
0618 {
0619 if (!wdrtas_nowayout)
0620 wdrtas_timer_stop();
0621
0622 wdrtas_unregister_devs();
0623
0624 unregister_reboot_notifier(&wdrtas_notifier);
0625 }
0626
0627 module_init(wdrtas_init);
0628 module_exit(wdrtas_exit);