Blame view

drivers/watchdog/wdrtas.c 14.6 KB
de6cc6515   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-or-later
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
   * RTAS calls are available
   */
  
  /*
   * RTAS watchdog driver
   *
   * (C) Copyright IBM Corp. 2005
   * device driver to exploit watchdog RTAS functions
   *
   * Authors : Utz Bacher <utz.bacher@de.ibm.com>
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
14
   */
27c766aaa   Joe Perches   watchdog: Use pr_...
15
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
16
17
18
19
20
21
22
23
24
  #include <linux/fs.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/miscdevice.h>
  #include <linux/module.h>
  #include <linux/notifier.h>
  #include <linux/reboot.h>
  #include <linux/types.h>
  #include <linux/watchdog.h>
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
25
  #include <linux/uaccess.h>
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
26
27
  
  #include <asm/rtas.h>
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
28
29
30
31
32
33
34
35
  
  #define WDRTAS_MAGIC_CHAR		42
  #define WDRTAS_SUPPORTED_MASK		(WDIOF_SETTIMEOUT | \
  					 WDIOF_MAGICCLOSE)
  
  MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
  MODULE_DESCRIPTION("RTAS watchdog driver");
  MODULE_LICENSE("GPL");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
36

86a1e1896   Wim Van Sebroeck   watchdog: nowayou...
37
  static bool wdrtas_nowayout = WATCHDOG_NOWAYOUT;
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
38
  static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
39
  static char wdrtas_expect_close;
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  
  static int wdrtas_interval;
  
  #define WDRTAS_THERMAL_SENSOR		3
  static int wdrtas_token_get_sensor_state;
  #define WDRTAS_SURVEILLANCE_IND		9000
  static int wdrtas_token_set_indicator;
  #define WDRTAS_SP_SPI			28
  static int wdrtas_token_get_sp;
  static int wdrtas_token_event_scan;
  
  #define WDRTAS_DEFAULT_INTERVAL		300
  
  #define WDRTAS_LOGBUFFER_LEN		128
  static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
  
  
  /*** watchdog access functions */
  
  /**
   * wdrtas_set_interval - sets the watchdog interval
   * @interval: new interval
   *
   * returns 0 on success, <0 on failures
   *
   * wdrtas_set_interval sets the watchdog keepalive interval by calling the
   * RTAS function set-indicator (surveillance). The unit of interval is
   * seconds.
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
69
70
  
  static int wdrtas_set_interval(int interval)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
71
72
73
74
75
76
77
78
79
  {
  	long result;
  	static int print_msg = 10;
  
  	/* rtas uses minutes */
  	interval = (interval + 59) / 60;
  
  	result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
  			   WDRTAS_SURVEILLANCE_IND, 0, interval);
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
80
  	if (result < 0 && print_msg) {
27c766aaa   Joe Perches   watchdog: Use pr_...
81
82
83
  		pr_err("setting the watchdog to %i timeout failed: %li
  ",
  		       interval, result);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
84
85
86
87
88
  		print_msg--;
  	}
  
  	return result;
  }
b6966b1be   Mark Nelson   powerpc/wdrtas: U...
89
  #define WDRTAS_SP_SPI_LEN 4
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
90
91
92
93
94
95
96
97
98
99
  /**
   * wdrtas_get_interval - returns the current watchdog interval
   * @fallback_value: value (in seconds) to use, if the RTAS call fails
   *
   * returns the interval
   *
   * wdrtas_get_interval returns the current watchdog keepalive interval
   * as reported by the RTAS function ibm,get-system-parameter. The unit
   * of the return value is seconds.
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
100
  static int wdrtas_get_interval(int fallback_value)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
101
102
  {
  	long result;
b6966b1be   Mark Nelson   powerpc/wdrtas: U...
103
  	char value[WDRTAS_SP_SPI_LEN];
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
104

b6966b1be   Mark Nelson   powerpc/wdrtas: U...
105
106
  	spin_lock(&rtas_data_buf_lock);
  	memset(rtas_data_buf, 0, WDRTAS_SP_SPI_LEN);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
107
  	result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
b6966b1be   Mark Nelson   powerpc/wdrtas: U...
108
109
110
111
112
  			   WDRTAS_SP_SPI, __pa(rtas_data_buf),
  			   WDRTAS_SP_SPI_LEN);
  
  	memcpy(value, rtas_data_buf, WDRTAS_SP_SPI_LEN);
  	spin_unlock(&rtas_data_buf_lock);
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
113
  	if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) {
27c766aaa   Joe Perches   watchdog: Use pr_...
114
115
116
  		pr_warn("could not get sp_spi watchdog timeout (%li). Continuing
  ",
  			result);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
117
118
119
120
121
122
123
124
125
126
127
128
129
  		return fallback_value;
  	}
  
  	/* rtas uses minutes */
  	return ((int)value[2]) * 60;
  }
  
  /**
   * wdrtas_timer_start - starts watchdog
   *
   * wdrtas_timer_start starts the watchdog by calling the RTAS function
   * set-interval (surveillance)
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
130
  static void wdrtas_timer_start(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
131
132
133
134
135
136
137
138
139
140
  {
  	wdrtas_set_interval(wdrtas_interval);
  }
  
  /**
   * wdrtas_timer_stop - stops watchdog
   *
   * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
   * set-interval (surveillance)
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
141
  static void wdrtas_timer_stop(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
142
143
144
145
146
  {
  	wdrtas_set_interval(0);
  }
  
  /**
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
147
148
149
150
151
152
   * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
   *
   * wdrtas_timer_keepalive restarts the watchdog timer by calling the
   * RTAS function event-scan and repeats these calls as long as there are
   * events available. All events will be dumped.
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
153
  static void wdrtas_timer_keepalive(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
154
155
156
157
158
159
160
161
162
  {
  	long result;
  
  	do {
  		result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
  				   RTAS_EVENT_SCAN_ALL_EVENTS, 0,
  				   (void *)__pa(wdrtas_logbuffer),
  				   WDRTAS_LOGBUFFER_LEN);
  		if (result < 0)
27c766aaa   Joe Perches   watchdog: Use pr_...
163
164
  			pr_err("event-scan failed: %li
  ", result);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
165
  		if (result == 0)
48388069b   Andy Shevchenko   watchdog: wdrtas:...
166
167
168
  			print_hex_dump(KERN_INFO, "dumping event, data: ",
  				DUMP_PREFIX_OFFSET, 16, 1,
  				wdrtas_logbuffer, WDRTAS_LOGBUFFER_LEN, false);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
169
170
171
172
173
174
175
176
177
178
179
  	} while (result == 0);
  }
  
  /**
   * wdrtas_get_temperature - returns current temperature
   *
   * returns temperature or <0 on failures
   *
   * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
   * uses the RTAS call get-sensor-state, token 3 to do so
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
180
  static int wdrtas_get_temperature(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
181
  {
5ba762c9b   Adrian Reber   powerpc/rtas: Fix...
182
  	int result;
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
183
  	int temperature = 0;
5ba762c9b   Adrian Reber   powerpc/rtas: Fix...
184
  	result = rtas_get_sensor(WDRTAS_THERMAL_SENSOR, 0, &temperature);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
185
186
  
  	if (result < 0)
27c766aaa   Joe Perches   watchdog: Use pr_...
187
188
  		pr_warn("reading the thermal sensor failed: %i
  ", result);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
189
190
191
192
193
194
195
196
197
198
199
200
  	else
  		temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
  
  	return temperature;
  }
  
  /**
   * wdrtas_get_status - returns the status of the watchdog
   *
   * returns a bitmask of defines WDIOF_... as defined in
   * include/linux/watchdog.h
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
201
  static int wdrtas_get_status(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
202
203
204
205
206
207
208
209
210
211
  {
  	return 0; /* TODO */
  }
  
  /**
   * wdrtas_get_boot_status - returns the reason for the last boot
   *
   * returns a bitmask of defines WDIOF_... as defined in
   * include/linux/watchdog.h, indicating why the watchdog rebooted the system
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
212
  static int wdrtas_get_boot_status(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  {
  	return 0; /* TODO */
  }
  
  /*** watchdog API and operations stuff */
  
  /* wdrtas_write - called when watchdog device is written to
   * @file: file structure
   * @buf: user buffer with data
   * @len: amount to data written
   * @ppos: position in file
   *
   * returns the number of successfully processed characters, which is always
   * the number of bytes passed to this function
   *
   * wdrtas_write processes all the data given to it and looks for the magic
   * character 'V'. This character allows the watchdog device to be closed
   * properly.
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
232
  static ssize_t wdrtas_write(struct file *file, const char __user *buf,
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
  	     size_t len, loff_t *ppos)
  {
  	int i;
  	char c;
  
  	if (!len)
  		goto out;
  
  	if (!wdrtas_nowayout) {
  		wdrtas_expect_close = 0;
  		/* look for 'V' */
  		for (i = 0; i < len; i++) {
  			if (get_user(c, buf + i))
  				return -EFAULT;
  			/* allow to close device */
  			if (c == 'V')
  				wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
  		}
  	}
  
  	wdrtas_timer_keepalive();
  
  out:
  	return len;
  }
  
  /**
   * wdrtas_ioctl - ioctl function for the watchdog device
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
261
262
263
264
265
266
267
268
   * @file: file structure
   * @cmd: command for ioctl
   * @arg: argument pointer
   *
   * returns 0 on success, <0 on failure
   *
   * wdrtas_ioctl implements the watchdog API ioctls
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
269
270
271
  
  static long wdrtas_ioctl(struct file *file, unsigned int cmd,
  							unsigned long arg)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
272
  {
e896fd986   Al Viro   [PATCH] wdrtas.c:...
273
  	int __user *argp = (void __user *)arg;
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
274
  	int i;
42747d712   Wim Van Sebroeck   [WATCHDOG] watchd...
275
  	static const struct watchdog_info wdinfo = {
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
276
277
  		.options = WDRTAS_SUPPORTED_MASK,
  		.firmware_version = 0,
7944d3a5a   Wim Van Sebroeck   [WATCHDOG] more c...
278
  		.identity = "wdrtas",
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
  	};
  
  	switch (cmd) {
  	case WDIOC_GETSUPPORT:
  		if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
  			return -EFAULT;
  		return 0;
  
  	case WDIOC_GETSTATUS:
  		i = wdrtas_get_status();
  		return put_user(i, argp);
  
  	case WDIOC_GETBOOTSTATUS:
  		i = wdrtas_get_boot_status();
  		return put_user(i, argp);
  
  	case WDIOC_GETTEMP:
  		if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
  			return -EOPNOTSUPP;
  
  		i = wdrtas_get_temperature();
  		return put_user(i, argp);
  
  	case WDIOC_SETOPTIONS:
  		if (get_user(i, argp))
  			return -EFAULT;
  		if (i & WDIOS_DISABLECARD)
  			wdrtas_timer_stop();
  		if (i & WDIOS_ENABLECARD) {
  			wdrtas_timer_keepalive();
  			wdrtas_timer_start();
  		}
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
311
  		/* not implemented. Done by H8
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
312
  		if (i & WDIOS_TEMPPANIC) {
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
313
  		} */
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
  		return 0;
  
  	case WDIOC_KEEPALIVE:
  		wdrtas_timer_keepalive();
  		return 0;
  
  	case WDIOC_SETTIMEOUT:
  		if (get_user(i, argp))
  			return -EFAULT;
  
  		if (wdrtas_set_interval(i))
  			return -EINVAL;
  
  		wdrtas_timer_keepalive();
  
  		if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
  			wdrtas_interval = i;
  		else
  			wdrtas_interval = wdrtas_get_interval(i);
  		/* fallthrough */
  
  	case WDIOC_GETTIMEOUT:
  		return put_user(wdrtas_interval, argp);
  
  	default:
795b89d20   Samuel Tardieu   [WATCHDOG] use EN...
339
  		return -ENOTTY;
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
340
341
342
343
344
345
346
347
348
349
350
351
352
  	}
  }
  
  /**
   * wdrtas_open - open function of watchdog device
   * @inode: inode structure
   * @file: file structure
   *
   * returns 0 on success, -EBUSY if the file has been opened already, <0 on
   * other failures
   *
   * function called when watchdog device is opened
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
353
  static int wdrtas_open(struct inode *inode, struct file *file)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
354
355
356
357
358
359
360
361
362
  {
  	/* only open once */
  	if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
  		atomic_dec(&wdrtas_miscdev_open);
  		return -EBUSY;
  	}
  
  	wdrtas_timer_start();
  	wdrtas_timer_keepalive();
c5bf68fe0   Kirill Smelkov   *: convert stream...
363
  	return stream_open(inode, file);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
364
365
366
367
368
369
370
371
372
373
374
  }
  
  /**
   * wdrtas_close - close function of watchdog device
   * @inode: inode structure
   * @file: file structure
   *
   * returns 0 on success
   *
   * close function. Always succeeds
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
375
  static int wdrtas_close(struct inode *inode, struct file *file)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
376
377
378
379
380
  {
  	/* only stop watchdog, if this was announced using 'V' before */
  	if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
  		wdrtas_timer_stop();
  	else {
27c766aaa   Joe Perches   watchdog: Use pr_...
381
382
  		pr_warn("got unexpected close. Watchdog not stopped.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  		wdrtas_timer_keepalive();
  	}
  
  	wdrtas_expect_close = 0;
  	atomic_dec(&wdrtas_miscdev_open);
  	return 0;
  }
  
  /**
   * wdrtas_temp_read - gives back the temperature in fahrenheit
   * @file: file structure
   * @buf: user buffer
   * @count: number of bytes to be read
   * @ppos: position in file
   *
   * returns always 1 or -EFAULT in case of user space copy failures, <0 on
   * other failures
   *
   * wdrtas_temp_read gives the temperature to the users by copying this
   * value as one byte into the user space buffer. The unit is Fahrenheit...
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
404
  static ssize_t wdrtas_temp_read(struct file *file, char __user *buf,
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  		 size_t count, loff_t *ppos)
  {
  	int temperature = 0;
  
  	temperature = wdrtas_get_temperature();
  	if (temperature < 0)
  		return temperature;
  
  	if (copy_to_user(buf, &temperature, 1))
  		return -EFAULT;
  
  	return 1;
  }
  
  /**
   * wdrtas_temp_open - open function of temperature device
   * @inode: inode structure
   * @file: file structure
   *
   * returns 0 on success, <0 on failure
   *
   * function called when temperature device is opened
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
428
  static int wdrtas_temp_open(struct inode *inode, struct file *file)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
429
  {
c5bf68fe0   Kirill Smelkov   *: convert stream...
430
  	return stream_open(inode, file);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
431
432
433
434
435
436
437
438
439
440
441
  }
  
  /**
   * wdrtas_temp_close - close function of temperature device
   * @inode: inode structure
   * @file: file structure
   *
   * returns 0 on success
   *
   * close function. Always succeeds
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
442
  static int wdrtas_temp_close(struct inode *inode, struct file *file)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
443
444
445
446
447
448
449
450
451
452
453
454
455
456
  {
  	return 0;
  }
  
  /**
   * wdrtas_reboot - reboot notifier function
   * @nb: notifier block structure
   * @code: reboot code
   * @ptr: unused
   *
   * returns NOTIFY_DONE
   *
   * wdrtas_reboot stops the watchdog in case of a reboot
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
457
458
  static int wdrtas_reboot(struct notifier_block *this,
  					unsigned long code, void *ptr)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
459
  {
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
460
  	if (code == SYS_DOWN || code == SYS_HALT)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
461
462
463
464
465
466
  		wdrtas_timer_stop();
  
  	return NOTIFY_DONE;
  }
  
  /*** initialization stuff */
62322d255   Arjan van de Ven   [PATCH] make more...
467
  static const struct file_operations wdrtas_fops = {
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
468
469
470
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.write		= wdrtas_write,
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
471
  	.unlocked_ioctl	= wdrtas_ioctl,
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
472
473
474
475
476
477
478
479
480
  	.open		= wdrtas_open,
  	.release	= wdrtas_close,
  };
  
  static struct miscdevice wdrtas_miscdev = {
  	.minor =	WATCHDOG_MINOR,
  	.name =		"watchdog",
  	.fops =		&wdrtas_fops,
  };
62322d255   Arjan van de Ven   [PATCH] make more...
481
  static const struct file_operations wdrtas_temp_fops = {
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
  	.owner		= THIS_MODULE,
  	.llseek		= no_llseek,
  	.read		= wdrtas_temp_read,
  	.open		= wdrtas_temp_open,
  	.release	= wdrtas_temp_close,
  };
  
  static struct miscdevice wdrtas_tempdev = {
  	.minor =	TEMP_MINOR,
  	.name =		"temperature",
  	.fops =		&wdrtas_temp_fops,
  };
  
  static struct notifier_block wdrtas_notifier = {
  	.notifier_call =	wdrtas_reboot,
  };
  
  /**
   * wdrtas_get_tokens - reads in RTAS tokens
   *
af901ca18   André Goddard Rosa   tree-wide: fix as...
502
   * returns 0 on success, <0 on failure
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
503
504
505
506
507
   *
   * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
   * this watchdog driver. It tolerates, if "get-sensor-state" and
   * "ibm,get-system-parameter" are not available.
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
508
  static int wdrtas_get_tokens(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
509
510
511
  {
  	wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
  	if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
27c766aaa   Joe Perches   watchdog: Use pr_...
512
513
  		pr_warn("couldn't get token for get-sensor-state. Trying to continue without temperature support.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
514
515
516
517
  	}
  
  	wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
  	if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
27c766aaa   Joe Perches   watchdog: Use pr_...
518
519
520
  		pr_warn("couldn't get token for ibm,get-system-parameter. Trying to continue with a default timeout value of %i seconds.
  ",
  			WDRTAS_DEFAULT_INTERVAL);
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
521
522
523
524
  	}
  
  	wdrtas_token_set_indicator = rtas_token("set-indicator");
  	if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
27c766aaa   Joe Perches   watchdog: Use pr_...
525
526
  		pr_err("couldn't get token for set-indicator. Terminating watchdog code.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
527
528
529
530
531
  		return -EIO;
  	}
  
  	wdrtas_token_event_scan = rtas_token("event-scan");
  	if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
27c766aaa   Joe Perches   watchdog: Use pr_...
532
533
  		pr_err("couldn't get token for event-scan. Terminating watchdog code.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
534
535
536
537
538
539
540
541
542
543
544
545
  		return -EIO;
  	}
  
  	return 0;
  }
  
  /**
   * wdrtas_unregister_devs - unregisters the misc dev handlers
   *
   * wdrtas_register_devs unregisters the watchdog and temperature watchdog
   * misc devs
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
546
  static void wdrtas_unregister_devs(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
547
548
549
550
551
552
553
554
555
  {
  	misc_deregister(&wdrtas_miscdev);
  	if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
  		misc_deregister(&wdrtas_tempdev);
  }
  
  /**
   * wdrtas_register_devs - registers the misc dev handlers
   *
af901ca18   André Goddard Rosa   tree-wide: fix as...
556
   * returns 0 on success, <0 on failure
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
557
558
559
560
   *
   * wdrtas_register_devs registers the watchdog and temperature watchdog
   * misc devs
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
561
  static int wdrtas_register_devs(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
562
563
564
565
566
  {
  	int result;
  
  	result = misc_register(&wdrtas_miscdev);
  	if (result) {
27c766aaa   Joe Perches   watchdog: Use pr_...
567
568
  		pr_err("couldn't register watchdog misc device. Terminating watchdog code.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
569
570
571
572
573
574
  		return result;
  	}
  
  	if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
  		result = misc_register(&wdrtas_tempdev);
  		if (result) {
27c766aaa   Joe Perches   watchdog: Use pr_...
575
576
  			pr_warn("couldn't register watchdog temperature misc device. Continuing without temperature support.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
577
578
579
580
581
582
583
584
585
586
  			wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
  		}
  	}
  
  	return 0;
  }
  
  /**
   * wdrtas_init - init function of the watchdog driver
   *
af901ca18   André Goddard Rosa   tree-wide: fix as...
587
   * returns 0 on success, <0 on failure
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
588
589
590
   *
   * registers the file handlers and the reboot notifier
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
591
  static int __init wdrtas_init(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
592
593
594
595
596
597
598
599
  {
  	if (wdrtas_get_tokens())
  		return -ENODEV;
  
  	if (wdrtas_register_devs())
  		return -ENODEV;
  
  	if (register_reboot_notifier(&wdrtas_notifier)) {
27c766aaa   Joe Perches   watchdog: Use pr_...
600
601
  		pr_err("could not register reboot notifier. Terminating watchdog code.
  ");
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
  		wdrtas_unregister_devs();
  		return -ENODEV;
  	}
  
  	if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
  		wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
  	else
  		wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
  
  	return 0;
  }
  
  /**
   * wdrtas_exit - exit function of the watchdog driver
   *
   * unregisters the file handlers and the reboot notifier
   */
dae67a283   Alan Cox   [WATCHDOG 54/57] ...
619
  static void __exit wdrtas_exit(void)
031f7edec   Utz Bacher   [PATCH] ppc64: ad...
620
621
622
623
624
625
626
627
628
629
630
  {
  	if (!wdrtas_nowayout)
  		wdrtas_timer_stop();
  
  	wdrtas_unregister_devs();
  
  	unregister_reboot_notifier(&wdrtas_notifier);
  }
  
  module_init(wdrtas_init);
  module_exit(wdrtas_exit);