diff options
author | Michael Holzheu <holzheu@de.ibm.com> | 2006-09-20 09:58:49 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2006-09-20 09:58:49 -0400 |
commit | ff6b8ea68f4b7353f88b97024f28127e2148aa00 (patch) | |
tree | 67ebb74cbbc042d99325ff33c3f80e4b3e0a1c42 /arch/s390/kernel/setup.c | |
parent | 331c982d4a6b43cdc0d056956a1cae8a7d6237bf (diff) |
[S390] ipl/dump on panic.
It is now possible to specify a ccw/fcp dump device which is used to
automatically create a system dump in case of a kernel panic. The dump
device can be configured under /sys/firmware/dump.
In addition it is now possible to specify a ccw/fcp device which is used
for the next reboot of Linux. The reipl device can be configured under
/sys/firmware/reipl.
Signed-off-by: Michael Holzheu <holzheu@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/setup.c')
-rw-r--r-- | arch/s390/kernel/setup.c | 220 |
1 files changed, 1 insertions, 219 deletions
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 89051e8a5d8d..f2a9165ca4f8 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -285,16 +285,9 @@ void (*_machine_power_off)(void) = machine_power_off_smp; | |||
285 | /* | 285 | /* |
286 | * Reboot, halt and power_off routines for non SMP. | 286 | * Reboot, halt and power_off routines for non SMP. |
287 | */ | 287 | */ |
288 | extern void reipl(unsigned long devno); | ||
289 | extern void reipl_diag(void); | ||
290 | static void do_machine_restart_nonsmp(char * __unused) | 288 | static void do_machine_restart_nonsmp(char * __unused) |
291 | { | 289 | { |
292 | reipl_diag(); | 290 | do_reipl(); |
293 | |||
294 | if (MACHINE_IS_VM) | ||
295 | cpcmd ("IPL", NULL, 0, NULL); | ||
296 | else | ||
297 | reipl (0x10000 | S390_lowcore.ipl_device); | ||
298 | } | 291 | } |
299 | 292 | ||
300 | static void do_machine_halt_nonsmp(void) | 293 | static void do_machine_halt_nonsmp(void) |
@@ -755,214 +748,3 @@ struct seq_operations cpuinfo_op = { | |||
755 | .show = show_cpuinfo, | 748 | .show = show_cpuinfo, |
756 | }; | 749 | }; |
757 | 750 | ||
758 | #define DEFINE_IPL_ATTR(_name, _format, _value) \ | ||
759 | static ssize_t ipl_##_name##_show(struct subsystem *subsys, \ | ||
760 | char *page) \ | ||
761 | { \ | ||
762 | return sprintf(page, _format, _value); \ | ||
763 | } \ | ||
764 | static struct subsys_attribute ipl_##_name##_attr = \ | ||
765 | __ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL); | ||
766 | |||
767 | DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long) | ||
768 | IPL_PARMBLOCK_START->fcp.wwpn); | ||
769 | DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long) | ||
770 | IPL_PARMBLOCK_START->fcp.lun); | ||
771 | DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long) | ||
772 | IPL_PARMBLOCK_START->fcp.bootprog); | ||
773 | DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long) | ||
774 | IPL_PARMBLOCK_START->fcp.br_lba); | ||
775 | |||
776 | enum ipl_type_type { | ||
777 | ipl_type_unknown, | ||
778 | ipl_type_ccw, | ||
779 | ipl_type_fcp, | ||
780 | }; | ||
781 | |||
782 | static enum ipl_type_type | ||
783 | get_ipl_type(void) | ||
784 | { | ||
785 | struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; | ||
786 | |||
787 | if (!IPL_DEVNO_VALID) | ||
788 | return ipl_type_unknown; | ||
789 | if (!IPL_PARMBLOCK_VALID) | ||
790 | return ipl_type_ccw; | ||
791 | if (ipl->hdr.header.version > IPL_MAX_SUPPORTED_VERSION) | ||
792 | return ipl_type_unknown; | ||
793 | if (ipl->fcp.pbt != IPL_TYPE_FCP) | ||
794 | return ipl_type_unknown; | ||
795 | return ipl_type_fcp; | ||
796 | } | ||
797 | |||
798 | static ssize_t | ||
799 | ipl_type_show(struct subsystem *subsys, char *page) | ||
800 | { | ||
801 | switch (get_ipl_type()) { | ||
802 | case ipl_type_ccw: | ||
803 | return sprintf(page, "ccw\n"); | ||
804 | case ipl_type_fcp: | ||
805 | return sprintf(page, "fcp\n"); | ||
806 | default: | ||
807 | return sprintf(page, "unknown\n"); | ||
808 | } | ||
809 | } | ||
810 | |||
811 | static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type); | ||
812 | |||
813 | static ssize_t | ||
814 | ipl_device_show(struct subsystem *subsys, char *page) | ||
815 | { | ||
816 | struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; | ||
817 | |||
818 | switch (get_ipl_type()) { | ||
819 | case ipl_type_ccw: | ||
820 | return sprintf(page, "0.0.%04x\n", ipl_devno); | ||
821 | case ipl_type_fcp: | ||
822 | return sprintf(page, "0.0.%04x\n", ipl->fcp.devno); | ||
823 | default: | ||
824 | return 0; | ||
825 | } | ||
826 | } | ||
827 | |||
828 | static struct subsys_attribute ipl_device_attr = | ||
829 | __ATTR(device, S_IRUGO, ipl_device_show, NULL); | ||
830 | |||
831 | static struct attribute *ipl_fcp_attrs[] = { | ||
832 | &ipl_type_attr.attr, | ||
833 | &ipl_device_attr.attr, | ||
834 | &ipl_wwpn_attr.attr, | ||
835 | &ipl_lun_attr.attr, | ||
836 | &ipl_bootprog_attr.attr, | ||
837 | &ipl_br_lba_attr.attr, | ||
838 | NULL, | ||
839 | }; | ||
840 | |||
841 | static struct attribute_group ipl_fcp_attr_group = { | ||
842 | .attrs = ipl_fcp_attrs, | ||
843 | }; | ||
844 | |||
845 | static struct attribute *ipl_ccw_attrs[] = { | ||
846 | &ipl_type_attr.attr, | ||
847 | &ipl_device_attr.attr, | ||
848 | NULL, | ||
849 | }; | ||
850 | |||
851 | static struct attribute_group ipl_ccw_attr_group = { | ||
852 | .attrs = ipl_ccw_attrs, | ||
853 | }; | ||
854 | |||
855 | static struct attribute *ipl_unknown_attrs[] = { | ||
856 | &ipl_type_attr.attr, | ||
857 | NULL, | ||
858 | }; | ||
859 | |||
860 | static struct attribute_group ipl_unknown_attr_group = { | ||
861 | .attrs = ipl_unknown_attrs, | ||
862 | }; | ||
863 | |||
864 | static ssize_t | ||
865 | ipl_parameter_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | ||
866 | { | ||
867 | unsigned int size = IPL_PARMBLOCK_SIZE; | ||
868 | |||
869 | if (off > size) | ||
870 | return 0; | ||
871 | if (off + count > size) | ||
872 | count = size - off; | ||
873 | |||
874 | memcpy(buf, (void *) IPL_PARMBLOCK_START + off, count); | ||
875 | return count; | ||
876 | } | ||
877 | |||
878 | static struct bin_attribute ipl_parameter_attr = { | ||
879 | .attr = { | ||
880 | .name = "binary_parameter", | ||
881 | .mode = S_IRUGO, | ||
882 | .owner = THIS_MODULE, | ||
883 | }, | ||
884 | .size = PAGE_SIZE, | ||
885 | .read = &ipl_parameter_read, | ||
886 | }; | ||
887 | |||
888 | static ssize_t | ||
889 | ipl_scp_data_read(struct kobject *kobj, char *buf, loff_t off, size_t count) | ||
890 | { | ||
891 | unsigned int size = IPL_PARMBLOCK_START->fcp.scp_data_len; | ||
892 | void *scp_data = &IPL_PARMBLOCK_START->fcp.scp_data; | ||
893 | |||
894 | if (off > size) | ||
895 | return 0; | ||
896 | if (off + count > size) | ||
897 | count = size - off; | ||
898 | |||
899 | memcpy(buf, scp_data + off, count); | ||
900 | return count; | ||
901 | } | ||
902 | |||
903 | static struct bin_attribute ipl_scp_data_attr = { | ||
904 | .attr = { | ||
905 | .name = "scp_data", | ||
906 | .mode = S_IRUGO, | ||
907 | .owner = THIS_MODULE, | ||
908 | }, | ||
909 | .size = PAGE_SIZE, | ||
910 | .read = &ipl_scp_data_read, | ||
911 | }; | ||
912 | |||
913 | static decl_subsys(ipl, NULL, NULL); | ||
914 | |||
915 | static int ipl_register_fcp_files(void) | ||
916 | { | ||
917 | int rc; | ||
918 | |||
919 | rc = sysfs_create_group(&ipl_subsys.kset.kobj, | ||
920 | &ipl_fcp_attr_group); | ||
921 | if (rc) | ||
922 | goto out; | ||
923 | rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, | ||
924 | &ipl_parameter_attr); | ||
925 | if (rc) | ||
926 | goto out_ipl_parm; | ||
927 | rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, | ||
928 | &ipl_scp_data_attr); | ||
929 | if (!rc) | ||
930 | goto out; | ||
931 | |||
932 | sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); | ||
933 | |||
934 | out_ipl_parm: | ||
935 | sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); | ||
936 | out: | ||
937 | return rc; | ||
938 | } | ||
939 | |||
940 | static int __init | ||
941 | ipl_device_sysfs_register(void) { | ||
942 | int rc; | ||
943 | |||
944 | rc = firmware_register(&ipl_subsys); | ||
945 | if (rc) | ||
946 | goto out; | ||
947 | |||
948 | switch (get_ipl_type()) { | ||
949 | case ipl_type_ccw: | ||
950 | rc = sysfs_create_group(&ipl_subsys.kset.kobj, | ||
951 | &ipl_ccw_attr_group); | ||
952 | break; | ||
953 | case ipl_type_fcp: | ||
954 | rc = ipl_register_fcp_files(); | ||
955 | break; | ||
956 | default: | ||
957 | rc = sysfs_create_group(&ipl_subsys.kset.kobj, | ||
958 | &ipl_unknown_attr_group); | ||
959 | break; | ||
960 | } | ||
961 | |||
962 | if (rc) | ||
963 | firmware_unregister(&ipl_subsys); | ||
964 | out: | ||
965 | return rc; | ||
966 | } | ||
967 | |||
968 | __initcall(ipl_device_sysfs_register); | ||