diff options
Diffstat (limited to 'arch/s390/kernel/ipl.c')
-rw-r--r-- | arch/s390/kernel/ipl.c | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c index 2c91226e1d40..13eacce62011 100644 --- a/arch/s390/kernel/ipl.c +++ b/arch/s390/kernel/ipl.c | |||
@@ -34,12 +34,14 @@ enum ipl_type { | |||
34 | IPL_TYPE_UNKNOWN = 2, | 34 | IPL_TYPE_UNKNOWN = 2, |
35 | IPL_TYPE_CCW = 4, | 35 | IPL_TYPE_CCW = 4, |
36 | IPL_TYPE_FCP = 8, | 36 | IPL_TYPE_FCP = 8, |
37 | IPL_TYPE_NSS = 16, | ||
37 | }; | 38 | }; |
38 | 39 | ||
39 | #define IPL_NONE_STR "none" | 40 | #define IPL_NONE_STR "none" |
40 | #define IPL_UNKNOWN_STR "unknown" | 41 | #define IPL_UNKNOWN_STR "unknown" |
41 | #define IPL_CCW_STR "ccw" | 42 | #define IPL_CCW_STR "ccw" |
42 | #define IPL_FCP_STR "fcp" | 43 | #define IPL_FCP_STR "fcp" |
44 | #define IPL_NSS_STR "nss" | ||
43 | 45 | ||
44 | static char *ipl_type_str(enum ipl_type type) | 46 | static char *ipl_type_str(enum ipl_type type) |
45 | { | 47 | { |
@@ -50,6 +52,8 @@ static char *ipl_type_str(enum ipl_type type) | |||
50 | return IPL_CCW_STR; | 52 | return IPL_CCW_STR; |
51 | case IPL_TYPE_FCP: | 53 | case IPL_TYPE_FCP: |
52 | return IPL_FCP_STR; | 54 | return IPL_FCP_STR; |
55 | case IPL_TYPE_NSS: | ||
56 | return IPL_NSS_STR; | ||
53 | case IPL_TYPE_UNKNOWN: | 57 | case IPL_TYPE_UNKNOWN: |
54 | default: | 58 | default: |
55 | return IPL_UNKNOWN_STR; | 59 | return IPL_UNKNOWN_STR; |
@@ -64,6 +68,7 @@ enum ipl_method { | |||
64 | IPL_METHOD_FCP_RO_DIAG, | 68 | IPL_METHOD_FCP_RO_DIAG, |
65 | IPL_METHOD_FCP_RW_DIAG, | 69 | IPL_METHOD_FCP_RW_DIAG, |
66 | IPL_METHOD_FCP_RO_VM, | 70 | IPL_METHOD_FCP_RO_VM, |
71 | IPL_METHOD_NSS, | ||
67 | }; | 72 | }; |
68 | 73 | ||
69 | enum shutdown_action { | 74 | enum shutdown_action { |
@@ -114,11 +119,14 @@ enum diag308_rc { | |||
114 | static int diag308_set_works = 0; | 119 | static int diag308_set_works = 0; |
115 | 120 | ||
116 | static int reipl_capabilities = IPL_TYPE_UNKNOWN; | 121 | static int reipl_capabilities = IPL_TYPE_UNKNOWN; |
122 | |||
117 | static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; | 123 | static enum ipl_type reipl_type = IPL_TYPE_UNKNOWN; |
118 | static enum ipl_method reipl_method = IPL_METHOD_NONE; | 124 | static enum ipl_method reipl_method = IPL_METHOD_NONE; |
119 | static struct ipl_parameter_block *reipl_block_fcp; | 125 | static struct ipl_parameter_block *reipl_block_fcp; |
120 | static struct ipl_parameter_block *reipl_block_ccw; | 126 | static struct ipl_parameter_block *reipl_block_ccw; |
121 | 127 | ||
128 | static char reipl_nss_name[NSS_NAME_SIZE + 1]; | ||
129 | |||
122 | static int dump_capabilities = IPL_TYPE_NONE; | 130 | static int dump_capabilities = IPL_TYPE_NONE; |
123 | static enum ipl_type dump_type = IPL_TYPE_NONE; | 131 | static enum ipl_type dump_type = IPL_TYPE_NONE; |
124 | static enum ipl_method dump_method = IPL_METHOD_NONE; | 132 | static enum ipl_method dump_method = IPL_METHOD_NONE; |
@@ -173,6 +181,24 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ | |||
173 | sys_##_prefix##_##_name##_show, \ | 181 | sys_##_prefix##_##_name##_show, \ |
174 | sys_##_prefix##_##_name##_store); | 182 | sys_##_prefix##_##_name##_store); |
175 | 183 | ||
184 | #define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\ | ||
185 | static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \ | ||
186 | char *page) \ | ||
187 | { \ | ||
188 | return sprintf(page, _fmt_out, _value); \ | ||
189 | } \ | ||
190 | static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\ | ||
191 | const char *buf, size_t len) \ | ||
192 | { \ | ||
193 | if (sscanf(buf, _fmt_in, _value) != 1) \ | ||
194 | return -EINVAL; \ | ||
195 | return len; \ | ||
196 | } \ | ||
197 | static struct subsys_attribute sys_##_prefix##_##_name##_attr = \ | ||
198 | __ATTR(_name,(S_IRUGO | S_IWUSR), \ | ||
199 | sys_##_prefix##_##_name##_show, \ | ||
200 | sys_##_prefix##_##_name##_store); | ||
201 | |||
176 | static void make_attrs_ro(struct attribute **attrs) | 202 | static void make_attrs_ro(struct attribute **attrs) |
177 | { | 203 | { |
178 | while (*attrs) { | 204 | while (*attrs) { |
@@ -189,6 +215,8 @@ static enum ipl_type ipl_get_type(void) | |||
189 | { | 215 | { |
190 | struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; | 216 | struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START; |
191 | 217 | ||
218 | if (ipl_flags & IPL_NSS_VALID) | ||
219 | return IPL_TYPE_NSS; | ||
192 | if (!(ipl_flags & IPL_DEVNO_VALID)) | 220 | if (!(ipl_flags & IPL_DEVNO_VALID)) |
193 | return IPL_TYPE_UNKNOWN; | 221 | return IPL_TYPE_UNKNOWN; |
194 | if (!(ipl_flags & IPL_PARMBLOCK_VALID)) | 222 | if (!(ipl_flags & IPL_PARMBLOCK_VALID)) |
@@ -324,6 +352,20 @@ static struct attribute_group ipl_ccw_attr_group = { | |||
324 | .attrs = ipl_ccw_attrs, | 352 | .attrs = ipl_ccw_attrs, |
325 | }; | 353 | }; |
326 | 354 | ||
355 | /* NSS ipl device attributes */ | ||
356 | |||
357 | DEFINE_IPL_ATTR_RO(ipl_nss, name, "%s\n", kernel_nss_name); | ||
358 | |||
359 | static struct attribute *ipl_nss_attrs[] = { | ||
360 | &sys_ipl_type_attr.attr, | ||
361 | &sys_ipl_nss_name_attr.attr, | ||
362 | NULL, | ||
363 | }; | ||
364 | |||
365 | static struct attribute_group ipl_nss_attr_group = { | ||
366 | .attrs = ipl_nss_attrs, | ||
367 | }; | ||
368 | |||
327 | /* UNKNOWN ipl device attributes */ | 369 | /* UNKNOWN ipl device attributes */ |
328 | 370 | ||
329 | static struct attribute *ipl_unknown_attrs[] = { | 371 | static struct attribute *ipl_unknown_attrs[] = { |
@@ -432,6 +474,21 @@ static struct attribute_group reipl_ccw_attr_group = { | |||
432 | .attrs = reipl_ccw_attrs, | 474 | .attrs = reipl_ccw_attrs, |
433 | }; | 475 | }; |
434 | 476 | ||
477 | |||
478 | /* NSS reipl device attributes */ | ||
479 | |||
480 | DEFINE_IPL_ATTR_STR_RW(reipl_nss, name, "%s\n", "%s\n", reipl_nss_name); | ||
481 | |||
482 | static struct attribute *reipl_nss_attrs[] = { | ||
483 | &sys_reipl_nss_name_attr.attr, | ||
484 | NULL, | ||
485 | }; | ||
486 | |||
487 | static struct attribute_group reipl_nss_attr_group = { | ||
488 | .name = IPL_NSS_STR, | ||
489 | .attrs = reipl_nss_attrs, | ||
490 | }; | ||
491 | |||
435 | /* reipl type */ | 492 | /* reipl type */ |
436 | 493 | ||
437 | static int reipl_set_type(enum ipl_type type) | 494 | static int reipl_set_type(enum ipl_type type) |
@@ -454,6 +511,9 @@ static int reipl_set_type(enum ipl_type type) | |||
454 | else | 511 | else |
455 | reipl_method = IPL_METHOD_FCP_RO_DIAG; | 512 | reipl_method = IPL_METHOD_FCP_RO_DIAG; |
456 | break; | 513 | break; |
514 | case IPL_TYPE_NSS: | ||
515 | reipl_method = IPL_METHOD_NSS; | ||
516 | break; | ||
457 | default: | 517 | default: |
458 | reipl_method = IPL_METHOD_NONE; | 518 | reipl_method = IPL_METHOD_NONE; |
459 | } | 519 | } |
@@ -475,6 +535,8 @@ static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf, | |||
475 | rc = reipl_set_type(IPL_TYPE_CCW); | 535 | rc = reipl_set_type(IPL_TYPE_CCW); |
476 | else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) | 536 | else if (strncmp(buf, IPL_FCP_STR, strlen(IPL_FCP_STR)) == 0) |
477 | rc = reipl_set_type(IPL_TYPE_FCP); | 537 | rc = reipl_set_type(IPL_TYPE_FCP); |
538 | else if (strncmp(buf, IPL_NSS_STR, strlen(IPL_NSS_STR)) == 0) | ||
539 | rc = reipl_set_type(IPL_TYPE_NSS); | ||
478 | return (rc != 0) ? rc : len; | 540 | return (rc != 0) ? rc : len; |
479 | } | 541 | } |
480 | 542 | ||
@@ -647,6 +709,10 @@ void do_reipl(void) | |||
647 | case IPL_METHOD_FCP_RO_VM: | 709 | case IPL_METHOD_FCP_RO_VM: |
648 | __cpcmd("IPL", NULL, 0, NULL); | 710 | __cpcmd("IPL", NULL, 0, NULL); |
649 | break; | 711 | break; |
712 | case IPL_METHOD_NSS: | ||
713 | sprintf(buf, "IPL %s", reipl_nss_name); | ||
714 | __cpcmd(buf, NULL, 0, NULL); | ||
715 | break; | ||
650 | case IPL_METHOD_NONE: | 716 | case IPL_METHOD_NONE: |
651 | default: | 717 | default: |
652 | if (MACHINE_IS_VM) | 718 | if (MACHINE_IS_VM) |
@@ -733,6 +799,10 @@ static int __init ipl_init(void) | |||
733 | case IPL_TYPE_FCP: | 799 | case IPL_TYPE_FCP: |
734 | rc = ipl_register_fcp_files(); | 800 | rc = ipl_register_fcp_files(); |
735 | break; | 801 | break; |
802 | case IPL_TYPE_NSS: | ||
803 | rc = sysfs_create_group(&ipl_subsys.kset.kobj, | ||
804 | &ipl_nss_attr_group); | ||
805 | break; | ||
736 | default: | 806 | default: |
737 | rc = sysfs_create_group(&ipl_subsys.kset.kobj, | 807 | rc = sysfs_create_group(&ipl_subsys.kset.kobj, |
738 | &ipl_unknown_attr_group); | 808 | &ipl_unknown_attr_group); |
@@ -755,6 +825,20 @@ static void __init reipl_probe(void) | |||
755 | free_page((unsigned long)buffer); | 825 | free_page((unsigned long)buffer); |
756 | } | 826 | } |
757 | 827 | ||
828 | static int __init reipl_nss_init(void) | ||
829 | { | ||
830 | int rc; | ||
831 | |||
832 | if (!MACHINE_IS_VM) | ||
833 | return 0; | ||
834 | rc = sysfs_create_group(&reipl_subsys.kset.kobj, &reipl_nss_attr_group); | ||
835 | if (rc) | ||
836 | return rc; | ||
837 | strncpy(reipl_nss_name, kernel_nss_name, NSS_NAME_SIZE + 1); | ||
838 | reipl_capabilities |= IPL_TYPE_NSS; | ||
839 | return 0; | ||
840 | } | ||
841 | |||
758 | static int __init reipl_ccw_init(void) | 842 | static int __init reipl_ccw_init(void) |
759 | { | 843 | { |
760 | int rc; | 844 | int rc; |
@@ -837,6 +921,9 @@ static int __init reipl_init(void) | |||
837 | rc = reipl_fcp_init(); | 921 | rc = reipl_fcp_init(); |
838 | if (rc) | 922 | if (rc) |
839 | return rc; | 923 | return rc; |
924 | rc = reipl_nss_init(); | ||
925 | if (rc) | ||
926 | return rc; | ||
840 | rc = reipl_set_type(ipl_get_type()); | 927 | rc = reipl_set_type(ipl_get_type()); |
841 | if (rc) | 928 | if (rc) |
842 | return rc; | 929 | return rc; |