aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/setup.c
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@de.ibm.com>2006-09-20 09:58:49 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2006-09-20 09:58:49 -0400
commitff6b8ea68f4b7353f88b97024f28127e2148aa00 (patch)
tree67ebb74cbbc042d99325ff33c3f80e4b3e0a1c42 /arch/s390/kernel/setup.c
parent331c982d4a6b43cdc0d056956a1cae8a7d6237bf (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.c220
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 */
288extern void reipl(unsigned long devno);
289extern void reipl_diag(void);
290static void do_machine_restart_nonsmp(char * __unused) 288static 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
300static void do_machine_halt_nonsmp(void) 293static 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) \
759static ssize_t ipl_##_name##_show(struct subsystem *subsys, \
760 char *page) \
761{ \
762 return sprintf(page, _format, _value); \
763} \
764static struct subsys_attribute ipl_##_name##_attr = \
765 __ATTR(_name, S_IRUGO, ipl_##_name##_show, NULL);
766
767DEFINE_IPL_ATTR(wwpn, "0x%016llx\n", (unsigned long long)
768 IPL_PARMBLOCK_START->fcp.wwpn);
769DEFINE_IPL_ATTR(lun, "0x%016llx\n", (unsigned long long)
770 IPL_PARMBLOCK_START->fcp.lun);
771DEFINE_IPL_ATTR(bootprog, "%lld\n", (unsigned long long)
772 IPL_PARMBLOCK_START->fcp.bootprog);
773DEFINE_IPL_ATTR(br_lba, "%lld\n", (unsigned long long)
774 IPL_PARMBLOCK_START->fcp.br_lba);
775
776enum ipl_type_type {
777 ipl_type_unknown,
778 ipl_type_ccw,
779 ipl_type_fcp,
780};
781
782static enum ipl_type_type
783get_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
798static ssize_t
799ipl_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
811static struct subsys_attribute ipl_type_attr = __ATTR_RO(ipl_type);
812
813static ssize_t
814ipl_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
828static struct subsys_attribute ipl_device_attr =
829 __ATTR(device, S_IRUGO, ipl_device_show, NULL);
830
831static 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
841static struct attribute_group ipl_fcp_attr_group = {
842 .attrs = ipl_fcp_attrs,
843};
844
845static struct attribute *ipl_ccw_attrs[] = {
846 &ipl_type_attr.attr,
847 &ipl_device_attr.attr,
848 NULL,
849};
850
851static struct attribute_group ipl_ccw_attr_group = {
852 .attrs = ipl_ccw_attrs,
853};
854
855static struct attribute *ipl_unknown_attrs[] = {
856 &ipl_type_attr.attr,
857 NULL,
858};
859
860static struct attribute_group ipl_unknown_attr_group = {
861 .attrs = ipl_unknown_attrs,
862};
863
864static ssize_t
865ipl_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
878static 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
888static ssize_t
889ipl_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
903static 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
913static decl_subsys(ipl, NULL, NULL);
914
915static 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
934out_ipl_parm:
935 sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group);
936out:
937 return rc;
938}
939
940static int __init
941ipl_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);
964out:
965 return rc;
966}
967
968__initcall(ipl_device_sysfs_register);