diff options
-rw-r--r-- | arch/powerpc/platforms/pseries/nvram.c | 70 |
1 files changed, 24 insertions, 46 deletions
diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c index 9f8671a44551..893f36053c97 100644 --- a/arch/powerpc/platforms/pseries/nvram.c +++ b/arch/powerpc/platforms/pseries/nvram.c | |||
@@ -569,35 +569,6 @@ error: | |||
569 | return ret; | 569 | return ret; |
570 | } | 570 | } |
571 | 571 | ||
572 | static 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 | |||
601 | static int nvram_pstore_open(struct pstore_info *psi) | 572 | static int nvram_pstore_open(struct pstore_info *psi) |
602 | { | 573 | { |
603 | /* Reset the iterator to start reading partitions again */ | 574 | /* Reset the iterator to start reading partitions again */ |
@@ -685,10 +656,9 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type, | |||
685 | unsigned int err_type, id_no, size = 0; | 656 | unsigned int err_type, id_no, size = 0; |
686 | struct nvram_os_partition *part = NULL; | 657 | struct nvram_os_partition *part = NULL; |
687 | char *buff = NULL, *big_buff = NULL; | 658 | char *buff = NULL, *big_buff = NULL; |
688 | int rc, sig = 0; | 659 | int sig = 0; |
689 | loff_t p; | 660 | loff_t p; |
690 | 661 | ||
691 | read_partition: | ||
692 | read_type++; | 662 | read_type++; |
693 | 663 | ||
694 | switch (nvram_type_ids[read_type]) { | 664 | switch (nvram_type_ids[read_type]) { |
@@ -749,30 +719,36 @@ read_partition: | |||
749 | *id = id_no; | 719 | *id = id_no; |
750 | 720 | ||
751 | if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { | 721 | if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) { |
722 | int length, unzipped_len; | ||
723 | |||
752 | oops_hdr = (struct oops_log_info *)buff; | 724 | oops_hdr = (struct oops_log_info *)buff; |
753 | *buf = buff + sizeof(*oops_hdr); | 725 | length = oops_hdr->report_length; |
726 | *buf = kmalloc(length, GFP_KERNEL); | ||
727 | if (*buf == NULL) | ||
728 | return -ENOMEM; | ||
729 | memcpy(*buf, buff + sizeof(*oops_hdr), length); | ||
730 | time->tv_sec = oops_hdr->timestamp; | ||
731 | time->tv_nsec = 0; | ||
732 | kfree(buff); | ||
754 | 733 | ||
755 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { | 734 | if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) { |
756 | big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); | 735 | big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL); |
757 | if (!big_buff) | 736 | if (!big_buff) |
758 | return -ENOMEM; | 737 | return -ENOMEM; |
759 | 738 | ||
760 | rc = unzip_oops(buff, big_buff); | 739 | unzipped_len = nvram_decompress(*buf, big_buff, |
740 | length, big_oops_buf_sz); | ||
761 | 741 | ||
762 | if (rc != 0) { | 742 | if (unzipped_len < 0) { |
763 | kfree(buff); | 743 | pr_err("nvram: decompression failed, returned " |
744 | "rc %d\n", unzipped_len); | ||
764 | kfree(big_buff); | 745 | kfree(big_buff); |
765 | goto read_partition; | 746 | } else { |
747 | *buf = big_buff; | ||
748 | length = unzipped_len; | ||
766 | } | 749 | } |
767 | |||
768 | oops_hdr = (struct oops_log_info *)big_buff; | ||
769 | *buf = big_buff + sizeof(*oops_hdr); | ||
770 | kfree(buff); | ||
771 | } | 750 | } |
772 | 751 | return length; | |
773 | time->tv_sec = oops_hdr->timestamp; | ||
774 | time->tv_nsec = 0; | ||
775 | return oops_hdr->report_length; | ||
776 | } | 752 | } |
777 | 753 | ||
778 | *buf = buff; | 754 | *buf = buff; |
@@ -816,6 +792,7 @@ static int nvram_pstore_init(void) | |||
816 | static void __init nvram_init_oops_partition(int rtas_partition_exists) | 792 | static void __init nvram_init_oops_partition(int rtas_partition_exists) |
817 | { | 793 | { |
818 | int rc; | 794 | int rc; |
795 | size_t size; | ||
819 | 796 | ||
820 | rc = pseries_nvram_init_os_partition(&oops_log_partition); | 797 | rc = pseries_nvram_init_os_partition(&oops_log_partition); |
821 | if (rc != 0) { | 798 | if (rc != 0) { |
@@ -844,8 +821,9 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists) | |||
844 | big_oops_buf_sz = (oops_data_sz * 100) / 45; | 821 | big_oops_buf_sz = (oops_data_sz * 100) / 45; |
845 | big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); | 822 | big_oops_buf = kmalloc(big_oops_buf_sz, GFP_KERNEL); |
846 | if (big_oops_buf) { | 823 | if (big_oops_buf) { |
847 | stream.workspace = kmalloc(zlib_deflate_workspacesize( | 824 | size = max(zlib_deflate_workspacesize(WINDOW_BITS, MEM_LEVEL), |
848 | WINDOW_BITS, MEM_LEVEL), GFP_KERNEL); | 825 | zlib_inflate_workspacesize()); |
826 | stream.workspace = kmalloc(size, GFP_KERNEL); | ||
849 | if (!stream.workspace) { | 827 | if (!stream.workspace) { |
850 | pr_err("nvram: No memory for compression workspace; " | 828 | pr_err("nvram: No memory for compression workspace; " |
851 | "skipping compression of %s partition data\n", | 829 | "skipping compression of %s partition data\n", |