| 1 | |
| 2 | |
| 3 | * Copyright (C) 2001 Anton Blanchard <[email protected]>, IBM
|
| 4 | *
|
| 5 | * Communication to userspace based on kernel/printk.c
|
| 6 |
|
| 7 |
|
| 8 | #include <linux/types.h>
|
| 9 | #include <linux/errno.h>
|
| 10 | #include <linux/sched.h>
|
| 11 | #include <linux/kernel.h>
|
| 12 | #include <linux/of.h>
|
| 13 | #include <linux/overflow.h>
|
| 14 | #include <linux/poll.h>
|
| 15 | #include <linux/proc_fs.h>
|
| 16 | #include <linux/init.h>
|
| 17 | #include <linux/vmalloc.h>
|
| 18 | #include <linux/spinlock.h>
|
| 19 | #include <linux/cpu.h>
|
| 20 | #include <linux/workqueue.h>
|
| 21 | #include <linux/slab.h>
|
| 22 | #include <linux/topology.h>
|
| 23 |
|
| 24 | #include <linux/uaccess.h>
|
| 25 | #include <asm/io.h>
|
| 26 | #include <asm/rtas.h>
|
| 27 | #include <asm/nvram.h>
|
| 28 | #include <linux/atomic.h>
|
| 29 | #include <asm/machdep.h>
|
| 30 | #include <asm/topology.h>
|
| 31 |
|
| 32 |
|
| 33 | static DEFINE_SPINLOCK(rtasd_log_lock);
|
| 34 |
|
| 35 | static DECLARE_WAIT_QUEUE_HEAD(rtas_log_wait);
|
| 36 |
|
| 37 | static char *rtas_log_buf;
|
| 38 | static unsigned long rtas_log_start;
|
| 39 | static unsigned long rtas_log_size;
|
| 40 |
|
| 41 | static int surveillance_timeout = -1;
|
| 42 |
|
| 43 | static unsigned int rtas_error_log_max;
|
| 44 | static unsigned int rtas_error_log_buffer_max;
|
| 45 |
|
| 46 |
|
| 47 | static unsigned int event_scan;
|
| 48 | static unsigned int rtas_event_scan_rate;
|
| 49 |
|
| 50 | static bool full_rtas_msgs;
|
| 51 |
|
| 52 |
|
| 53 | static int logging_enabled; |
| 54 | * make sure we don't try logging
|
| 55 | * anything
|
| 56 | static int error_log_cnt;
|
| 57 |
|
| 58 | |
| 59 | * Since we use 32 bit RTAS, the physical address of this must be below
|
| 60 | * 4G or else bad things happen. Allocate this in the kernel data and
|
| 61 | * make it big enough.
|
| 62 |
|
| 63 | static unsigned char logdata[RTAS_ERROR_LOG_MAX];
|
| 64 |
|
| 65 | static char *rtas_type[] = {
|
| 66 | "Unknown", "Retry", "TCE Error", "Internal Device Failure",
|
| 67 | "Timeout", "Data Parity", "Address Parity", "Cache Parity",
|
| 68 | "Address Invalid", "ECC Uncorrected", "ECC Corrupted",
|
| 69 | };
|
| 70 |
|
| 71 | static char *rtas_event_type(int type)
|
| 72 | {
|
| 73 | if ((type > 0) && (type < 11))
|
| 74 | return rtas_type[type];
|
| 75 |
|
| 76 | switch (type) {
|
| 77 | case RTAS_TYPE_EPOW:
|
| 78 | return "EPOW";
|
| 79 | case RTAS_TYPE_PLATFORM:
|
| 80 | return "Platform Error";
|
| 81 | case RTAS_TYPE_IO:
|
| 82 | return "I/O Event";
|
| 83 | case RTAS_TYPE_INFO:
|
| 84 | return "Platform Information Event";
|
| 85 | case RTAS_TYPE_DEALLOC:
|
| 86 | return "Resource Deallocation Event";
|
| 87 | case RTAS_TYPE_DUMP:
|
| 88 | return "Dump Notification Event";
|
| 89 | case RTAS_TYPE_PRRN:
|
| 90 | return "Platform Resource Reassignment Event";
|
| 91 | case RTAS_TYPE_HOTPLUG:
|
| 92 | return "Hotplug Event";
|
| 93 | case RTAS_TYPE_HVPIPE:
|
| 94 | return "Hypervisor Pipe Notification event";
|
| 95 | }
|
| 96 |
|
| 97 | return rtas_type[0];
|
| 98 | }
|
| 99 |
|
| 100 | |
| 101 | * will be collected together with obvious begin/end.
|
| 102 | * There will be a unique identifier on the begin and end lines.
|
| 103 | * This will persist across reboots.
|
| 104 | *
|
| 105 | * format of error logs returned from RTAS:
|
| 106 | * bytes (size) : contents
|
| 107 | * --------------------------------------------------------
|
| 108 | * 0-7 (8) : rtas_error_log
|
| 109 | * 8-47 (40) : extended info
|
| 110 | * 48-51 (4) : vendor id
|
| 111 | * 52-1023 (vendor specific) : location code and debug data
|
| 112 |
|
| 113 | static void printk_log_rtas(char *buf, int len)
|
| 114 | {
|
| 115 |
|
| 116 | int i,j,n = 0;
|
| 117 | int perline = 16;
|
| 118 | char buffer[64];
|
| 119 | char * str = "RTAS event";
|
| 120 |
|
| 121 | if (full_rtas_msgs) {
|
| 122 | printk(RTAS_DEBUG "%d -------- %s begin --------\n",
|
| 123 | error_log_cnt, str);
|
| 124 |
|
| 125 | |
| 126 | * Print perline bytes on each line, each line will start
|
| 127 | * with RTAS and a changing number, so syslogd will
|
| 128 | * print lines that are otherwise the same. Separate every
|
| 129 | * 4 bytes with a space.
|
| 130 |
|
| 131 | for (i = 0; i < len; i++) {
|
| 132 | j = i % perline;
|
| 133 | if (j == 0) {
|
| 134 | memset(buffer, 0, sizeof(buffer));
|
| 135 | n = sprintf(buffer, "RTAS %d:", i/perline);
|
| 136 | }
|
| 137 |
|
| 138 | if ((i % 4) == 0)
|
| 139 | n += sprintf(buffer+n, " ");
|
| 140 |
|
| 141 | n += sprintf(buffer+n, "%02x", (unsigned char)buf[i]);
|
| 142 |
|
| 143 | if (j == (perline-1))
|
| 144 | printk(KERN_DEBUG "%s\n", buffer);
|
| 145 | }
|
| 146 | if ((i % perline) != 0)
|
| 147 | printk(KERN_DEBUG "%s\n", buffer);
|
| 148 |
|
| 149 | printk(RTAS_DEBUG "%d -------- %s end ----------\n",
|
| 150 | error_log_cnt, str);
|
| 151 | } else {
|
| 152 | struct rtas_error_log *errlog = (struct rtas_error_log *)buf;
|
| 153 |
|
| 154 | printk(RTAS_DEBUG "event: %d, Type: %s (%d), Severity: %d\n",
|
| 155 | error_log_cnt,
|
| 156 | rtas_event_type(rtas_error_type(errlog)),
|
| 157 | rtas_error_type(errlog),
|
| 158 | rtas_error_severity(errlog));
|
| 159 | }
|
| 160 | }
|
| 161 |
|
| 162 | static int log_rtas_len(char * buf)
|
| 163 | {
|
| 164 | size_t len;
|
| 165 | struct rtas_error_log *err;
|
| 166 | u32 extended_log_length;
|
| 167 |
|
| 168 | err = (struct rtas_error_log *)buf;
|
| 169 | extended_log_length = rtas_error_extended(err) ? rtas_error_extended_log_length(err) : 0;
|
| 170 | len = struct_size(err, buffer, extended_log_length);
|
| 171 |
|
| 172 | if (rtas_error_log_max == 0)
|
| 173 | rtas_error_log_max = rtas_get_error_log_max();
|
| 174 | len = min(len, rtas_error_log_max);
|
| 175 |
|
| 176 | return len;
|
| 177 | }
|
| 178 |
|
| 179 | |
| 180 | * First write to nvram, if fatal error, that is the only
|
| 181 | * place we log the info. The error will be picked up
|
| 182 | * on the next reboot by rtasd. If not fatal, run the
|
| 183 | * method for the type of error. Currently, only RTAS
|
| 184 | * errors have methods implemented, but in the future
|
| 185 | * there might be a need to store data in nvram before a
|
| 186 | * call to panic().
|
| 187 | *
|
| 188 | * XXX We write to nvram periodically, to indicate error has
|
| 189 | * been written and sync'd, but there is a possibility
|
| 190 | * that if we don't shutdown correctly, a duplicate error
|
| 191 | * record will be created on next reboot.
|
| 192 |
|
| 193 | void pSeries_log_error(char *buf, unsigned int err_type, int fatal)
|
| 194 | {
|
| 195 | unsigned long offset;
|
| 196 | unsigned long s;
|
| 197 | int len = 0;
|
| 198 |
|
| 199 | pr_debug("rtasd: logging event\n");
|
| 200 | if (buf == NULL)
|
| 201 | return;
|
| 202 |
|
| 203 | spin_lock_irqsave(&rtasd_log_lock, s);
|
| 204 |
|
| 205 |
|
| 206 | switch (err_type & ERR_TYPE_MASK) {
|
| 207 | case ERR_TYPE_RTAS_LOG:
|
| 208 | len = log_rtas_len(buf);
|
| 209 | if (!(err_type & ERR_FLAG_BOOT))
|
| 210 | error_log_cnt++;
|
| 211 | break;
|
| 212 | case ERR_TYPE_KERNEL_PANIC:
|
| 213 | default:
|
| 214 | WARN_ON_ONCE(!irqs_disabled());
|
| 215 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 216 | return;
|
| 217 | }
|
| 218 |
|
| 219 | #ifdef CONFIG_PPC64
|
| 220 |
|
| 221 | if (logging_enabled && !(err_type & ERR_FLAG_BOOT))
|
| 222 | nvram_write_error_log(buf, len, err_type, error_log_cnt);
|
| 223 | #endif
|
| 224 |
|
| 225 | |
| 226 | * rtas errors can occur during boot, and we do want to capture
|
| 227 | * those somewhere, even if nvram isn't ready (why not?), and even
|
| 228 | * if rtasd isn't ready. Put them into the boot log, at least.
|
| 229 |
|
| 230 | if ((err_type & ERR_TYPE_MASK) == ERR_TYPE_RTAS_LOG)
|
| 231 | printk_log_rtas(buf, len);
|
| 232 |
|
| 233 |
|
| 234 | if (fatal || !logging_enabled) {
|
| 235 | logging_enabled = 0;
|
| 236 | WARN_ON_ONCE(!irqs_disabled());
|
| 237 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 238 | return;
|
| 239 | }
|
| 240 |
|
| 241 |
|
| 242 | switch (err_type & ERR_TYPE_MASK) {
|
| 243 | case ERR_TYPE_RTAS_LOG:
|
| 244 | offset = rtas_error_log_buffer_max *
|
| 245 | ((rtas_log_start+rtas_log_size) & LOG_NUMBER_MASK);
|
| 246 |
|
| 247 |
|
| 248 | memcpy(&rtas_log_buf[offset], (void *) &error_log_cnt, sizeof(int));
|
| 249 |
|
| 250 |
|
| 251 | offset += sizeof(int);
|
| 252 | memcpy(&rtas_log_buf[offset], buf, len);
|
| 253 |
|
| 254 | if (rtas_log_size < LOG_NUMBER)
|
| 255 | rtas_log_size += 1;
|
| 256 | else
|
| 257 | rtas_log_start += 1;
|
| 258 |
|
| 259 | WARN_ON_ONCE(!irqs_disabled());
|
| 260 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 261 | wake_up_interruptible(&rtas_log_wait);
|
| 262 | break;
|
| 263 | case ERR_TYPE_KERNEL_PANIC:
|
| 264 | default:
|
| 265 | WARN_ON_ONCE(!irqs_disabled());
|
| 266 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 267 | return;
|
| 268 | }
|
| 269 | }
|
| 270 |
|
| 271 | static void handle_rtas_event(const struct rtas_error_log *log)
|
| 272 | {
|
| 273 | if (!machine_is(pseries))
|
| 274 | return;
|
| 275 |
|
| 276 | if (rtas_error_type(log) == RTAS_TYPE_PRRN)
|
| 277 | pr_info_ratelimited("Platform resource reassignment ignored.\n");
|
| 278 | }
|
| 279 |
|
| 280 | static int rtas_log_open(struct inode * inode, struct file * file)
|
| 281 | {
|
| 282 | return 0;
|
| 283 | }
|
| 284 |
|
| 285 | static int rtas_log_release(struct inode * inode, struct file * file)
|
| 286 | {
|
| 287 | return 0;
|
| 288 | }
|
| 289 |
|
| 290 | |
| 291 | * know that we can safely clear the events in NVRAM.
|
| 292 | * Next we'll sit and wait for something else to log.
|
| 293 |
|
| 294 | static ssize_t rtas_log_read(struct file * file, char __user * buf,
|
| 295 | size_t count, loff_t *ppos)
|
| 296 | {
|
| 297 | int error;
|
| 298 | char *tmp;
|
| 299 | unsigned long s;
|
| 300 | unsigned long offset;
|
| 301 |
|
| 302 | if (!buf || count < rtas_error_log_buffer_max)
|
| 303 | return -EINVAL;
|
| 304 |
|
| 305 | count = rtas_error_log_buffer_max;
|
| 306 |
|
| 307 | if (!access_ok(buf, count))
|
| 308 | return -EFAULT;
|
| 309 |
|
| 310 | tmp = kmalloc(count, GFP_KERNEL);
|
| 311 | if (!tmp)
|
| 312 | return -ENOMEM;
|
| 313 |
|
| 314 | spin_lock_irqsave(&rtasd_log_lock, s);
|
| 315 |
|
| 316 |
|
| 317 | while (rtas_log_size == 0) {
|
| 318 | if (file->f_flags & O_NONBLOCK) {
|
| 319 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 320 | error = -EAGAIN;
|
| 321 | goto out;
|
| 322 | }
|
| 323 |
|
| 324 | if (!logging_enabled) {
|
| 325 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 326 | error = -ENODATA;
|
| 327 | goto out;
|
| 328 | }
|
| 329 | #ifdef CONFIG_PPC64
|
| 330 | nvram_clear_error_log();
|
| 331 | #endif
|
| 332 |
|
| 333 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 334 | error = wait_event_interruptible(rtas_log_wait, rtas_log_size);
|
| 335 | if (error)
|
| 336 | goto out;
|
| 337 | spin_lock_irqsave(&rtasd_log_lock, s);
|
| 338 | }
|
| 339 |
|
| 340 | offset = rtas_error_log_buffer_max * (rtas_log_start & LOG_NUMBER_MASK);
|
| 341 | memcpy(tmp, &rtas_log_buf[offset], count);
|
| 342 |
|
| 343 | rtas_log_start += 1;
|
| 344 | rtas_log_size -= 1;
|
| 345 | spin_unlock_irqrestore(&rtasd_log_lock, s);
|
| 346 |
|
| 347 | error = copy_to_user(buf, tmp, count) ? -EFAULT : count;
|
| 348 | out:
|
| 349 | kfree(tmp);
|
| 350 | return error;
|
| 351 | }
|
| 352 |
|
| 353 | static __poll_t rtas_log_poll(struct file *file, poll_table * wait)
|
| 354 | {
|
| 355 | poll_wait(file, &rtas_log_wait, wait);
|
| 356 | if (rtas_log_size)
|
| 357 | return EPOLLIN | EPOLLRDNORM;
|
| 358 | return 0;
|
| 359 | }
|
| 360 |
|
| 361 | static const struct proc_ops rtas_log_proc_ops = {
|
| 362 | .proc_read = rtas_log_read,
|
| 363 | .proc_poll = rtas_log_poll,
|
| 364 | .proc_open = rtas_log_open,
|
| 365 | .proc_release = rtas_log_release,
|
| 366 | .proc_lseek = noop_llseek,
|
| 367 | };
|
| 368 |
|
| 369 | static int enable_surveillance(int timeout)
|
| 370 | {
|
| 371 | int error;
|
| 372 |
|
| 373 | error = rtas_set_indicator(SURVEILLANCE_TOKEN, 0, timeout);
|
| 374 |
|
| 375 | if (error == 0)
|
| 376 | return 0;
|
| 377 |
|
| 378 | if (error == -EINVAL) {
|
| 379 | printk(KERN_DEBUG "rtasd: surveillance not supported\n");
|
| 380 | return 0;
|
| 381 | }
|
| 382 |
|
| 383 | printk(KERN_ERR "rtasd: could not update surveillance\n");
|
| 384 | return -1;
|
| 385 | }
|
| 386 |
|
| 387 | static void do_event_scan(void)
|
| 388 | {
|
| 389 | int error;
|
| 390 | do {
|
| 391 | memset(logdata, 0, rtas_error_log_max);
|
| 392 | error = rtas_call(event_scan, 4, 1, NULL,
|
| 393 | RTAS_EVENT_SCAN_ALL_EVENTS, 0,
|
| 394 | __pa(logdata), rtas_error_log_max);
|
| 395 | if (error == -1) {
|
| 396 | printk(KERN_ERR "event-scan failed\n");
|
| 397 | break;
|
| 398 | }
|
| 399 |
|
| 400 | if (error == 0) {
|
| 401 | if (rtas_error_type((struct rtas_error_log *)logdata) !=
|
| 402 | RTAS_TYPE_PRRN)
|
| 403 | pSeries_log_error(logdata, ERR_TYPE_RTAS_LOG,
|
| 404 | 0);
|
| 405 | handle_rtas_event((struct rtas_error_log *)logdata);
|
| 406 | }
|
| 407 |
|
| 408 | } while(error == 0);
|
| 409 | }
|
| 410 |
|
| 411 | static void rtas_event_scan(struct work_struct *w);
|
| 412 | static DECLARE_DELAYED_WORK(event_scan_work, rtas_event_scan);
|
| 413 |
|
| 414 | |
| 415 | * Delay should be at least one second since some machines have problems if
|
| 416 | * we call event-scan too quickly.
|
| 417 |
|
| 418 | static unsigned long event_scan_delay = 1*HZ;
|
| 419 | static int first_pass = 1;
|
| 420 |
|
| 421 | static void rtas_event_scan(struct work_struct *w)
|
| 422 | {
|
| 423 | unsigned int cpu;
|
| 424 |
|
| 425 | do_event_scan();
|
| 426 |
|
| 427 | cpus_read_lock();
|
| 428 |
|
| 429 |
|
| 430 | cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
|
| 431 | if (cpu >= nr_cpu_ids) {
|
| 432 | cpu = cpumask_first(cpu_online_mask);
|
| 433 |
|
| 434 | if (first_pass) {
|
| 435 | first_pass = 0;
|
| 436 | event_scan_delay = 30*HZ/rtas_event_scan_rate;
|
| 437 |
|
| 438 | if (surveillance_timeout != -1) {
|
| 439 | pr_debug("rtasd: enabling surveillance\n");
|
| 440 | enable_surveillance(surveillance_timeout);
|
| 441 | pr_debug("rtasd: surveillance enabled\n");
|
| 442 | }
|
| 443 | }
|
| 444 | }
|
| 445 |
|
| 446 | schedule_delayed_work_on(cpu, &event_scan_work,
|
| 447 | __round_jiffies_relative(event_scan_delay, cpu));
|
| 448 |
|
| 449 | cpus_read_unlock();
|
| 450 | }
|
| 451 |
|
| 452 | #ifdef CONFIG_PPC64
|
| 453 | static void __init retrieve_nvram_error_log(void)
|
| 454 | {
|
| 455 | unsigned int err_type ;
|
| 456 | int rc ;
|
| 457 |
|
| 458 |
|
| 459 | memset(logdata, 0, rtas_error_log_max);
|
| 460 | rc = nvram_read_error_log(logdata, rtas_error_log_max,
|
| 461 | &err_type, &error_log_cnt);
|
| 462 |
|
| 463 | logging_enabled = 1;
|
| 464 | if (!rc) {
|
| 465 | if (err_type != ERR_FLAG_ALREADY_LOGGED) {
|
| 466 | pSeries_log_error(logdata, err_type | ERR_FLAG_BOOT, 0);
|
| 467 | }
|
| 468 | }
|
| 469 | }
|
| 470 | #else
|
| 471 | static void __init retrieve_nvram_error_log(void)
|
| 472 | {
|
| 473 | }
|
| 474 | #endif
|
| 475 |
|
| 476 | static void __init start_event_scan(void)
|
| 477 | {
|
| 478 | printk(KERN_DEBUG "RTAS daemon started\n");
|
| 479 | pr_debug("rtasd: will sleep for %d milliseconds\n",
|
| 480 | (30000 / rtas_event_scan_rate));
|
| 481 |
|
| 482 |
|
| 483 | retrieve_nvram_error_log();
|
| 484 |
|
| 485 | schedule_delayed_work_on(cpumask_first(cpu_online_mask),
|
| 486 | &event_scan_work, event_scan_delay);
|
| 487 | }
|
| 488 |
|
| 489 |
|
| 490 | void rtas_cancel_event_scan(void)
|
| 491 | {
|
| 492 | cancel_delayed_work_sync(&event_scan_work);
|
| 493 | }
|
| 494 | EXPORT_SYMBOL_GPL(rtas_cancel_event_scan);
|
| 495 |
|
| 496 | static int __init rtas_event_scan_init(void)
|
| 497 | {
|
| 498 | int err;
|
| 499 |
|
| 500 | if (!machine_is(pseries) && !machine_is(chrp))
|
| 501 | return 0;
|
| 502 |
|
| 503 |
|
| 504 | event_scan = rtas_function_token(RTAS_FN_EVENT_SCAN);
|
| 505 | if (event_scan == RTAS_UNKNOWN_SERVICE) {
|
| 506 | printk(KERN_INFO "rtasd: No event-scan on system\n");
|
| 507 | return -ENODEV;
|
| 508 | }
|
| 509 |
|
| 510 | err = of_property_read_u32(rtas.dev, "rtas-event-scan-rate", &rtas_event_scan_rate);
|
| 511 | if (err) {
|
| 512 | printk(KERN_ERR "rtasd: no rtas-event-scan-rate on system\n");
|
| 513 | return -ENODEV;
|
| 514 | }
|
| 515 |
|
| 516 | if (!rtas_event_scan_rate) {
|
| 517 |
|
| 518 | printk(KERN_DEBUG "rtasd: scan rate is 0, not scanning\n");
|
| 519 | return 0;
|
| 520 | }
|
| 521 |
|
| 522 |
|
| 523 | rtas_error_log_max = rtas_get_error_log_max();
|
| 524 | rtas_error_log_buffer_max = rtas_error_log_max + sizeof(int);
|
| 525 |
|
| 526 | rtas_log_buf = vmalloc(array_size(LOG_NUMBER,
|
| 527 | rtas_error_log_buffer_max));
|
| 528 | if (!rtas_log_buf) {
|
| 529 | printk(KERN_ERR "rtasd: no memory\n");
|
| 530 | return -ENOMEM;
|
| 531 | }
|
| 532 |
|
| 533 | start_event_scan();
|
| 534 |
|
| 535 | return 0;
|
| 536 | }
|
| 537 | arch_initcall(rtas_event_scan_init);
|
| 538 |
|
| 539 | static int __init rtas_init(void)
|
| 540 | {
|
| 541 | struct proc_dir_entry *entry;
|
| 542 |
|
| 543 | if (!machine_is(pseries) && !machine_is(chrp))
|
| 544 | return 0;
|
| 545 |
|
| 546 | if (!rtas_log_buf)
|
| 547 | return -ENODEV;
|
| 548 |
|
| 549 | entry = proc_create("powerpc/rtas/error_log", 0400, NULL,
|
| 550 | &rtas_log_proc_ops);
|
| 551 | if (!entry)
|
| 552 | printk(KERN_ERR "Failed to create error_log proc entry\n");
|
| 553 |
|
| 554 | return 0;
|
| 555 | }
|
| 556 | __initcall(rtas_init);
|
| 557 |
|
| 558 | static int __init surveillance_setup(char *str)
|
| 559 | {
|
| 560 | int i;
|
| 561 |
|
| 562 |
|
| 563 | if (!machine_is(pseries))
|
| 564 | return 0;
|
| 565 |
|
| 566 | if (get_option(&str,&i)) {
|
| 567 | if (i >= 0 && i <= 255)
|
| 568 | surveillance_timeout = i;
|
| 569 | }
|
| 570 |
|
| 571 | return 1;
|
| 572 | }
|
| 573 | __setup("surveillance=", surveillance_setup);
|
| 574 |
|
| 575 | static int __init rtasmsgs_setup(char *str)
|
| 576 | {
|
| 577 | return (kstrtobool(str, &full_rtas_msgs) == 0);
|
| 578 | }
|
| 579 | __setup("rtasmsgs=", rtasmsgs_setup);
|