aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/pseries/nvram.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 13:29:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-04 13:29:23 -0400
commit65b97fb7303050fc826e518cf67fc283da23314f (patch)
tree595e7f04d65d95a39d65bd2dcf2385b3b6ea7969 /arch/powerpc/platforms/pseries/nvram.c
parentddcf6600b133697adbafd96e080818bdc0dfd028 (diff)
parent1d8b368ab4aacfc3f864655baad4d31a3028ec1a (diff)
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc
Pull powerpc updates from Ben Herrenschmidt: "This is the powerpc changes for the 3.11 merge window. In addition to the usual bug fixes and small updates, the main highlights are: - Support for transparent huge pages by Aneesh Kumar for 64-bit server processors. This allows the use of 16M pages as transparent huge pages on kernels compiled with a 64K base page size. - Base VFIO support for KVM on power by Alexey Kardashevskiy - Wiring up of our nvram to the pstore infrastructure, including putting compressed oopses in there by Aruna Balakrishnaiah - Move, rework and improve our "EEH" (basically PCI error handling and recovery) infrastructure. It is no longer specific to pseries but is now usable by the new "powernv" platform as well (no hypervisor) by Gavin Shan. - I fixed some bugs in our math-emu instruction decoding and made it usable to emulate some optional FP instructions on processors with hard FP that lack them (such as fsqrt on Freescale embedded processors). - Support for Power8 "Event Based Branch" facility by Michael Ellerman. This facility allows what is basically "userspace interrupts" for performance monitor events. - A bunch of Transactional Memory vs. Signals bug fixes and HW breakpoint/watchpoint fixes by Michael Neuling. And more ... I appologize in advance if I've failed to highlight something that somebody deemed worth it." * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (156 commits) pstore: Add hsize argument in write_buf call of pstore_ftrace_call powerpc/fsl: add MPIC timer wakeup support powerpc/mpic: create mpic subsystem object powerpc/mpic: add global timer support powerpc/mpic: add irq_set_wake support powerpc/85xx: enable coreint for all the 64bit boards powerpc/8xx: Erroneous double irq_eoi() on CPM IRQ in MPC8xx powerpc/fsl: Enable CONFIG_E1000E in mpc85xx_smp_defconfig powerpc/mpic: Add get_version API both for internal and external use powerpc: Handle both new style and old style reserve maps powerpc/hw_brk: Fix off by one error when validating DAWR region end powerpc/pseries: Support compression of oops text via pstore powerpc/pseries: Re-organise the oops compression code pstore: Pass header size in the pstore write callback powerpc/powernv: Fix iommu initialization again powerpc/pseries: Inform the hypervisor we are using EBB regs powerpc/perf: Add power8 EBB support powerpc/perf: Core EBB support for 64-bit book3s powerpc/perf: Drop MMCRA from thread_struct powerpc/perf: Don't enable if we have zero events ...
Diffstat (limited to 'arch/powerpc/platforms/pseries/nvram.c')
-rw-r--r--arch/powerpc/platforms/pseries/nvram.c554
1 files changed, 453 insertions, 101 deletions
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
index 8733a86ad52e..9f8671a44551 100644
--- a/arch/powerpc/platforms/pseries/nvram.c
+++ b/arch/powerpc/platforms/pseries/nvram.c
@@ -18,6 +18,7 @@
18#include <linux/spinlock.h> 18#include <linux/spinlock.h>
19#include <linux/slab.h> 19#include <linux/slab.h>
20#include <linux/kmsg_dump.h> 20#include <linux/kmsg_dump.h>
21#include <linux/pstore.h>
21#include <linux/ctype.h> 22#include <linux/ctype.h>
22#include <linux/zlib.h> 23#include <linux/zlib.h>
23#include <asm/uaccess.h> 24#include <asm/uaccess.h>
@@ -29,6 +30,13 @@
29/* Max bytes to read/write in one go */ 30/* Max bytes to read/write in one go */
30#define NVRW_CNT 0x20 31#define NVRW_CNT 0x20
31 32
33/*
34 * Set oops header version to distingush between old and new format header.
35 * lnx,oops-log partition max size is 4000, header version > 4000 will
36 * help in identifying new header.
37 */
38#define OOPS_HDR_VERSION 5000
39
32static unsigned int nvram_size; 40static unsigned int nvram_size;
33static int nvram_fetch, nvram_store; 41static int nvram_fetch, nvram_store;
34static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ 42static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */
@@ -45,20 +53,23 @@ struct nvram_os_partition {
45 int min_size; /* minimum acceptable size (0 means req_size) */ 53 int min_size; /* minimum acceptable size (0 means req_size) */
46 long size; /* size of data portion (excluding err_log_info) */ 54 long size; /* size of data portion (excluding err_log_info) */
47 long index; /* offset of data portion of partition */ 55 long index; /* offset of data portion of partition */
56 bool os_partition; /* partition initialized by OS, not FW */
48}; 57};
49 58
50static struct nvram_os_partition rtas_log_partition = { 59static struct nvram_os_partition rtas_log_partition = {
51 .name = "ibm,rtas-log", 60 .name = "ibm,rtas-log",
52 .req_size = 2079, 61 .req_size = 2079,
53 .min_size = 1055, 62 .min_size = 1055,
54 .index = -1 63 .index = -1,
64 .os_partition = true
55}; 65};
56 66
57static struct nvram_os_partition oops_log_partition = { 67static struct nvram_os_partition oops_log_partition = {
58 .name = "lnx,oops-log", 68 .name = "lnx,oops-log",
59 .req_size = 4000, 69 .req_size = 4000,
60 .min_size = 2000, 70 .min_size = 2000,
61 .index = -1 71 .index = -1,
72 .os_partition = true
62}; 73};
63 74
64static const char *pseries_nvram_os_partitions[] = { 75static const char *pseries_nvram_os_partitions[] = {
@@ -67,6 +78,12 @@ static const char *pseries_nvram_os_partitions[] = {
67 NULL 78 NULL
68}; 79};
69 80
81struct oops_log_info {
82 u16 version;
83 u16 report_length;
84 u64 timestamp;
85} __attribute__((packed));
86
70static void oops_to_nvram(struct kmsg_dumper *dumper, 87static void oops_to_nvram(struct kmsg_dumper *dumper,
71 enum kmsg_dump_reason reason); 88 enum kmsg_dump_reason reason);
72 89
@@ -83,28 +100,28 @@ static unsigned long last_unread_rtas_event; /* timestamp */
83 100
84 * big_oops_buf[] holds the uncompressed text we're capturing. 101 * big_oops_buf[] holds the uncompressed text we're capturing.
85 * 102 *
86 * oops_buf[] holds the compressed text, preceded by a prefix. 103 * oops_buf[] holds the compressed text, preceded by a oops header.
87 * The prefix is just a u16 holding the length of the compressed* text. 104 * oops header has u16 holding the version of oops header (to differentiate
88 * (*Or uncompressed, if compression fails.) oops_buf[] gets written 105 * between old and new format header) followed by u16 holding the length of
89 * to NVRAM. 106 * the compressed* text (*Or uncompressed, if compression fails.) and u64
107 * holding the timestamp. oops_buf[] gets written to NVRAM.
90 * 108 *
91 * oops_len points to the prefix. oops_data points to the compressed text. 109 * oops_log_info points to the header. oops_data points to the compressed text.
92 * 110 *
93 * +- oops_buf 111 * +- oops_buf
94 * | +- oops_data 112 * | +- oops_data
95 * v v 113 * v v
96 * +------------+-----------------------------------------------+ 114 * +-----------+-----------+-----------+------------------------+
97 * | length | text | 115 * | version | length | timestamp | text |
98 * | (2 bytes) | (oops_data_sz bytes) | 116 * | (2 bytes) | (2 bytes) | (8 bytes) | (oops_data_sz bytes) |
99 * +------------+-----------------------------------------------+ 117 * +-----------+-----------+-----------+------------------------+
100 * ^ 118 * ^
101 * +- oops_len 119 * +- oops_log_info
102 * 120 *
103 * We preallocate these buffers during init to avoid kmalloc during oops/panic. 121 * We preallocate these buffers during init to avoid kmalloc during oops/panic.
104 */ 122 */
105static size_t big_oops_buf_sz; 123static size_t big_oops_buf_sz;
106static char *big_oops_buf, *oops_buf; 124static char *big_oops_buf, *oops_buf;
107static u16 *oops_len;
108static char *oops_data; 125static char *oops_data;
109static size_t oops_data_sz; 126static size_t oops_data_sz;
110 127
@@ -114,6 +131,30 @@ static size_t oops_data_sz;
114#define MEM_LEVEL 4 131#define MEM_LEVEL 4
115static struct z_stream_s stream; 132static struct z_stream_s stream;
116 133
134#ifdef CONFIG_PSTORE
135static struct nvram_os_partition of_config_partition = {
136 .name = "of-config",
137 .index = -1,
138 .os_partition = false
139};
140
141static struct nvram_os_partition common_partition = {
142 .name = "common",
143 .index = -1,
144 .os_partition = false
145};
146
147static enum pstore_type_id nvram_type_ids[] = {
148 PSTORE_TYPE_DMESG,
149 PSTORE_TYPE_PPC_RTAS,
150 PSTORE_TYPE_PPC_OF,
151 PSTORE_TYPE_PPC_COMMON,
152 -1
153};
154static int read_type;
155static unsigned long last_rtas_event;
156#endif
157
117static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) 158static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
118{ 159{
119 unsigned int i; 160 unsigned int i;
@@ -275,48 +316,72 @@ int nvram_write_error_log(char * buff, int length,
275{ 316{
276 int rc = nvram_write_os_partition(&rtas_log_partition, buff, length, 317 int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
277 err_type, error_log_cnt); 318 err_type, error_log_cnt);
278 if (!rc) 319 if (!rc) {
279 last_unread_rtas_event = get_seconds(); 320 last_unread_rtas_event = get_seconds();
321#ifdef CONFIG_PSTORE
322 last_rtas_event = get_seconds();
323#endif
324 }
325
280 return rc; 326 return rc;
281} 327}
282 328
283/* nvram_read_error_log 329/* nvram_read_partition
284 * 330 *
285 * Reads nvram for error log for at most 'length' 331 * Reads nvram partition for at most 'length'
286 */ 332 */
287int nvram_read_error_log(char * buff, int length, 333int nvram_read_partition(struct nvram_os_partition *part, char *buff,
288 unsigned int * err_type, unsigned int * error_log_cnt) 334 int length, unsigned int *err_type,
335 unsigned int *error_log_cnt)
289{ 336{
290 int rc; 337 int rc;
291 loff_t tmp_index; 338 loff_t tmp_index;
292 struct err_log_info info; 339 struct err_log_info info;
293 340
294 if (rtas_log_partition.index == -1) 341 if (part->index == -1)
295 return -1; 342 return -1;
296 343
297 if (length > rtas_log_partition.size) 344 if (length > part->size)
298 length = rtas_log_partition.size; 345 length = part->size;
299 346
300 tmp_index = rtas_log_partition.index; 347 tmp_index = part->index;
301 348
302 rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index); 349 if (part->os_partition) {
303 if (rc <= 0) { 350 rc = ppc_md.nvram_read((char *)&info,
304 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); 351 sizeof(struct err_log_info),
305 return rc; 352 &tmp_index);
353 if (rc <= 0) {
354 pr_err("%s: Failed nvram_read (%d)\n", __FUNCTION__,
355 rc);
356 return rc;
357 }
306 } 358 }
307 359
308 rc = ppc_md.nvram_read(buff, length, &tmp_index); 360 rc = ppc_md.nvram_read(buff, length, &tmp_index);
309 if (rc <= 0) { 361 if (rc <= 0) {
310 printk(KERN_ERR "nvram_read_error_log: Failed nvram_read (%d)\n", rc); 362 pr_err("%s: Failed nvram_read (%d)\n", __FUNCTION__, rc);
311 return rc; 363 return rc;
312 } 364 }
313 365
314 *error_log_cnt = info.seq_num; 366 if (part->os_partition) {
315 *err_type = info.error_type; 367 *error_log_cnt = info.seq_num;
368 *err_type = info.error_type;
369 }
316 370
317 return 0; 371 return 0;
318} 372}
319 373
374/* nvram_read_error_log
375 *
376 * Reads nvram for error log for at most 'length'
377 */
378int nvram_read_error_log(char *buff, int length,
379 unsigned int *err_type, unsigned int *error_log_cnt)
380{
381 return nvram_read_partition(&rtas_log_partition, buff, length,
382 err_type, error_log_cnt);
383}
384
320/* This doesn't actually zero anything, but it sets the event_logged 385/* This doesn't actually zero anything, but it sets the event_logged
321 * word to tell that this event is safely in syslog. 386 * word to tell that this event is safely in syslog.
322 */ 387 */
@@ -405,6 +470,349 @@ static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
405 return 0; 470 return 0;
406} 471}
407 472
473/*
474 * Are we using the ibm,rtas-log for oops/panic reports? And if so,
475 * would logging this oops/panic overwrite an RTAS event that rtas_errd
476 * hasn't had a chance to read and process? Return 1 if so, else 0.
477 *
478 * We assume that if rtas_errd hasn't read the RTAS event in
479 * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
480 */
481static int clobbering_unread_rtas_event(void)
482{
483 return (oops_log_partition.index == rtas_log_partition.index
484 && last_unread_rtas_event
485 && get_seconds() - last_unread_rtas_event <=
486 NVRAM_RTAS_READ_TIMEOUT);
487}
488
489/* Derived from logfs_compress() */
490static int nvram_compress(const void *in, void *out, size_t inlen,
491 size_t outlen)
492{
493 int err, ret;
494
495 ret = -EIO;
496 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
497 MEM_LEVEL, Z_DEFAULT_STRATEGY);
498 if (err != Z_OK)
499 goto error;
500
501 stream.next_in = in;
502 stream.avail_in = inlen;
503 stream.total_in = 0;
504 stream.next_out = out;
505 stream.avail_out = outlen;
506 stream.total_out = 0;
507
508 err = zlib_deflate(&stream, Z_FINISH);
509 if (err != Z_STREAM_END)
510 goto error;
511
512 err = zlib_deflateEnd(&stream);
513 if (err != Z_OK)
514 goto error;
515
516 if (stream.total_out >= stream.total_in)
517 goto error;
518
519 ret = stream.total_out;
520error:
521 return ret;
522}
523
524/* Compress the text from big_oops_buf into oops_buf. */
525static int zip_oops(size_t text_len)
526{
527 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
528 int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
529 oops_data_sz);
530 if (zipped_len < 0) {
531 pr_err("nvram: compression failed; returned %d\n", zipped_len);
532 pr_err("nvram: logging uncompressed oops/panic report\n");
533 return -1;
534 }
535 oops_hdr->version = OOPS_HDR_VERSION;
536 oops_hdr->report_length = (u16) zipped_len;
537 oops_hdr->timestamp = get_seconds();
538 return 0;
539}
540
541#ifdef CONFIG_PSTORE
542/* Derived from logfs_uncompress */
543int nvram_decompress(void *in, void *out, size_t inlen, size_t outlen)
544{
545 int err, ret;
546
547 ret = -EIO;
548 err = zlib_inflateInit(&stream);
549 if (err != Z_OK)
550 goto error;
551
552 stream.next_in = in;
553 stream.avail_in = inlen;
554 stream.total_in = 0;
555 stream.next_out = out;
556 stream.avail_out = outlen;
557 stream.total_out = 0;
558
559 err = zlib_inflate(&stream, Z_FINISH);
560 if (err != Z_STREAM_END)
561 goto error;
562
563 err = zlib_inflateEnd(&stream);
564 if (err != Z_OK)
565 goto error;
566
567 ret = stream.total_out;
568error:
569 return ret;
570}
571
572static int unzip_oops(char *oops_buf, char *big_buf)
573{
574 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
575 u64 timestamp = oops_hdr->timestamp;
576 char *big_oops_data = NULL;
577 char *oops_data_buf = NULL;
578 size_t big_oops_data_sz;
579 int unzipped_len;
580
581 big_oops_data = big_buf + sizeof(struct oops_log_info);
582 big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info);
583 oops_data_buf = oops_buf + sizeof(struct oops_log_info);
584
585 unzipped_len = nvram_decompress(oops_data_buf, big_oops_data,
586 oops_hdr->report_length,
587 big_oops_data_sz);
588
589 if (unzipped_len < 0) {
590 pr_err("nvram: decompression failed; returned %d\n",
591 unzipped_len);
592 return -1;
593 }
594 oops_hdr = (struct oops_log_info *)big_buf;
595 oops_hdr->version = OOPS_HDR_VERSION;
596 oops_hdr->report_length = (u16) unzipped_len;
597 oops_hdr->timestamp = timestamp;
598 return 0;
599}
600
601static int nvram_pstore_open(struct pstore_info *psi)
602{
603 /* Reset the iterator to start reading partitions again */
604 read_type = -1;
605 return 0;
606}
607
608/**
609 * nvram_pstore_write - pstore write callback for nvram
610 * @type: Type of message logged
611 * @reason: reason behind dump (oops/panic)
612 * @id: identifier to indicate the write performed
613 * @part: pstore writes data to registered buffer in parts,
614 * part number will indicate the same.
615 * @count: Indicates oops count
616 * @hsize: Size of header added by pstore
617 * @size: number of bytes written to the registered buffer
618 * @psi: registered pstore_info structure
619 *
620 * Called by pstore_dump() when an oops or panic report is logged in the
621 * printk buffer.
622 * Returns 0 on successful write.
623 */
624static int nvram_pstore_write(enum pstore_type_id type,
625 enum kmsg_dump_reason reason,
626 u64 *id, unsigned int part, int count,
627 size_t hsize, size_t size,
628 struct pstore_info *psi)
629{
630 int rc;
631 unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
632 struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
633
634 /* part 1 has the recent messages from printk buffer */
635 if (part > 1 || type != PSTORE_TYPE_DMESG ||
636 clobbering_unread_rtas_event())
637 return -1;
638
639 oops_hdr->version = OOPS_HDR_VERSION;
640 oops_hdr->report_length = (u16) size;
641 oops_hdr->timestamp = get_seconds();
642
643 if (big_oops_buf) {
644 rc = zip_oops(size);
645 /*
646 * If compression fails copy recent log messages from
647 * big_oops_buf to oops_data.
648 */
649 if (rc != 0) {
650 size_t diff = size - oops_data_sz + hsize;
651
652 if (size > oops_data_sz) {
653 memcpy(oops_data, big_oops_buf, hsize);
654 memcpy(oops_data + hsize, big_oops_buf + diff,
655 oops_data_sz - hsize);
656
657 oops_hdr->report_length = (u16) oops_data_sz;
658 } else
659 memcpy(oops_data, big_oops_buf, size);
660 } else
661 err_type = ERR_TYPE_KERNEL_PANIC_GZ;
662 }
663
664 rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
665 (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
666 count);
667
668 if (rc != 0)
669 return rc;
670
671 *id = part;
672 return 0;
673}
674
675/*
676 * Reads the oops/panic report, rtas, of-config and common partition.
677 * Returns the length of the data we read from each partition.
678 * Returns 0 if we've been called before.
679 */
680static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
681 int *count, struct timespec *time, char **buf,
682 struct pstore_info *psi)
683{
684 struct oops_log_info *oops_hdr;
685 unsigned int err_type, id_no, size = 0;
686 struct nvram_os_partition *part = NULL;
687 char *buff = NULL, *big_buff = NULL;
688 int rc, sig = 0;
689 loff_t p;
690
691read_partition:
692 read_type++;
693
694 switch (nvram_type_ids[read_type]) {
695 case PSTORE_TYPE_DMESG:
696 part = &oops_log_partition;
697 *type = PSTORE_TYPE_DMESG;
698 break;
699 case PSTORE_TYPE_PPC_RTAS:
700 part = &rtas_log_partition;
701 *type = PSTORE_TYPE_PPC_RTAS;
702 time->tv_sec = last_rtas_event;
703 time->tv_nsec = 0;
704 break;
705 case PSTORE_TYPE_PPC_OF:
706 sig = NVRAM_SIG_OF;
707 part = &of_config_partition;
708 *type = PSTORE_TYPE_PPC_OF;
709 *id = PSTORE_TYPE_PPC_OF;
710 time->tv_sec = 0;
711 time->tv_nsec = 0;
712 break;
713 case PSTORE_TYPE_PPC_COMMON:
714 sig = NVRAM_SIG_SYS;
715 part = &common_partition;
716 *type = PSTORE_TYPE_PPC_COMMON;
717 *id = PSTORE_TYPE_PPC_COMMON;
718 time->tv_sec = 0;
719 time->tv_nsec = 0;
720 break;
721 default:
722 return 0;
723 }
724
725 if (!part->os_partition) {
726 p = nvram_find_partition(part->name, sig, &size);
727 if (p <= 0) {
728 pr_err("nvram: Failed to find partition %s, "
729 "err %d\n", part->name, (int)p);
730 return 0;
731 }
732 part->index = p;
733 part->size = size;
734 }
735
736 buff = kmalloc(part->size, GFP_KERNEL);
737
738 if (!buff)
739 return -ENOMEM;
740
741 if (nvram_read_partition(part, buff, part->size, &err_type, &id_no)) {
742 kfree(buff);
743 return 0;
744 }
745
746 *count = 0;
747
748 if (part->os_partition)
749 *id = id_no;
750
751 if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
752 oops_hdr = (struct oops_log_info *)buff;
753 *buf = buff + sizeof(*oops_hdr);
754
755 if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) {
756 big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL);
757 if (!big_buff)
758 return -ENOMEM;
759
760 rc = unzip_oops(buff, big_buff);
761
762 if (rc != 0) {
763 kfree(buff);
764 kfree(big_buff);
765 goto read_partition;
766 }
767
768 oops_hdr = (struct oops_log_info *)big_buff;
769 *buf = big_buff + sizeof(*oops_hdr);
770 kfree(buff);
771 }
772
773 time->tv_sec = oops_hdr->timestamp;
774 time->tv_nsec = 0;
775 return oops_hdr->report_length;
776 }
777
778 *buf = buff;
779 return part->size;
780}
781
782static struct pstore_info nvram_pstore_info = {
783 .owner = THIS_MODULE,
784 .name = "nvram",
785 .open = nvram_pstore_open,
786 .read = nvram_pstore_read,
787 .write = nvram_pstore_write,
788};
789
790static int nvram_pstore_init(void)
791{
792 int rc = 0;
793
794 if (big_oops_buf) {
795 nvram_pstore_info.buf = big_oops_buf;
796 nvram_pstore_info.bufsize = big_oops_buf_sz;
797 } else {
798 nvram_pstore_info.buf = oops_data;
799 nvram_pstore_info.bufsize = oops_data_sz;
800 }
801
802 rc = pstore_register(&nvram_pstore_info);
803 if (rc != 0)
804 pr_err("nvram: pstore_register() failed, defaults to "
805 "kmsg_dump; returned %d\n", rc);
806
807 return rc;
808}
809#else
810static int nvram_pstore_init(void)
811{
812 return -1;
813}
814#endif
815
408static void __init nvram_init_oops_partition(int rtas_partition_exists) 816static void __init nvram_init_oops_partition(int rtas_partition_exists)
409{ 817{
410 int rc; 818 int rc;
@@ -425,9 +833,8 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
425 oops_log_partition.name); 833 oops_log_partition.name);
426 return; 834 return;
427 } 835 }
428 oops_len = (u16*) oops_buf; 836 oops_data = oops_buf + sizeof(struct oops_log_info);
429 oops_data = oops_buf + sizeof(u16); 837 oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
430 oops_data_sz = oops_log_partition.size - sizeof(u16);
431 838
432 /* 839 /*
433 * Figure compression (preceded by elimination of each line's <n> 840 * Figure compression (preceded by elimination of each line's <n>
@@ -452,6 +859,11 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
452 stream.workspace = NULL; 859 stream.workspace = NULL;
453 } 860 }
454 861
862 rc = nvram_pstore_init();
863
864 if (!rc)
865 return;
866
455 rc = kmsg_dump_register(&nvram_kmsg_dumper); 867 rc = kmsg_dump_register(&nvram_kmsg_dumper);
456 if (rc != 0) { 868 if (rc != 0) {
457 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc); 869 pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
@@ -501,70 +913,6 @@ int __init pSeries_nvram_init(void)
501 return 0; 913 return 0;
502} 914}
503 915
504/*
505 * Are we using the ibm,rtas-log for oops/panic reports? And if so,
506 * would logging this oops/panic overwrite an RTAS event that rtas_errd
507 * hasn't had a chance to read and process? Return 1 if so, else 0.
508 *
509 * We assume that if rtas_errd hasn't read the RTAS event in
510 * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
511 */
512static int clobbering_unread_rtas_event(void)
513{
514 return (oops_log_partition.index == rtas_log_partition.index
515 && last_unread_rtas_event
516 && get_seconds() - last_unread_rtas_event <=
517 NVRAM_RTAS_READ_TIMEOUT);
518}
519
520/* Derived from logfs_compress() */
521static int nvram_compress(const void *in, void *out, size_t inlen,
522 size_t outlen)
523{
524 int err, ret;
525
526 ret = -EIO;
527 err = zlib_deflateInit2(&stream, COMPR_LEVEL, Z_DEFLATED, WINDOW_BITS,
528 MEM_LEVEL, Z_DEFAULT_STRATEGY);
529 if (err != Z_OK)
530 goto error;
531
532 stream.next_in = in;
533 stream.avail_in = inlen;
534 stream.total_in = 0;
535 stream.next_out = out;
536 stream.avail_out = outlen;
537 stream.total_out = 0;
538
539 err = zlib_deflate(&stream, Z_FINISH);
540 if (err != Z_STREAM_END)
541 goto error;
542
543 err = zlib_deflateEnd(&stream);
544 if (err != Z_OK)
545 goto error;
546
547 if (stream.total_out >= stream.total_in)
548 goto error;
549
550 ret = stream.total_out;
551error:
552 return ret;
553}
554
555/* Compress the text from big_oops_buf into oops_buf. */
556static int zip_oops(size_t text_len)
557{
558 int zipped_len = nvram_compress(big_oops_buf, oops_data, text_len,
559 oops_data_sz);
560 if (zipped_len < 0) {
561 pr_err("nvram: compression failed; returned %d\n", zipped_len);
562 pr_err("nvram: logging uncompressed oops/panic report\n");
563 return -1;
564 }
565 *oops_len = (u16) zipped_len;
566 return 0;
567}
568 916
569/* 917/*
570 * This is our kmsg_dump callback, called after an oops or panic report 918 * This is our kmsg_dump callback, called after an oops or panic report
@@ -576,6 +924,7 @@ static int zip_oops(size_t text_len)
576static void oops_to_nvram(struct kmsg_dumper *dumper, 924static void oops_to_nvram(struct kmsg_dumper *dumper,
577 enum kmsg_dump_reason reason) 925 enum kmsg_dump_reason reason)
578{ 926{
927 struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
579 static unsigned int oops_count = 0; 928 static unsigned int oops_count = 0;
580 static bool panicking = false; 929 static bool panicking = false;
581 static DEFINE_SPINLOCK(lock); 930 static DEFINE_SPINLOCK(lock);
@@ -619,14 +968,17 @@ static void oops_to_nvram(struct kmsg_dumper *dumper,
619 } 968 }
620 if (rc != 0) { 969 if (rc != 0) {
621 kmsg_dump_rewind(dumper); 970 kmsg_dump_rewind(dumper);
622 kmsg_dump_get_buffer(dumper, true, 971 kmsg_dump_get_buffer(dumper, false,
623 oops_data, oops_data_sz, &text_len); 972 oops_data, oops_data_sz, &text_len);
624 err_type = ERR_TYPE_KERNEL_PANIC; 973 err_type = ERR_TYPE_KERNEL_PANIC;
625 *oops_len = (u16) text_len; 974 oops_hdr->version = OOPS_HDR_VERSION;
975 oops_hdr->report_length = (u16) text_len;
976 oops_hdr->timestamp = get_seconds();
626 } 977 }
627 978
628 (void) nvram_write_os_partition(&oops_log_partition, oops_buf, 979 (void) nvram_write_os_partition(&oops_log_partition, oops_buf,
629 (int) (sizeof(*oops_len) + *oops_len), err_type, ++oops_count); 980 (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
981 ++oops_count);
630 982
631 spin_unlock_irqrestore(&lock, flags); 983 spin_unlock_irqrestore(&lock, flags);
632} 984}