aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>2014-08-26 11:51:08 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2014-09-01 03:56:29 -0400
commit69928601676ff6f51ff71ba943f749afe7b1cbb2 (patch)
tree69bc55d8ba4fd2c271b5305320fff8e6caadbf1a
parent3b1269350b15e46aba8cdd1613a07530253275cd (diff)
s390/ipl: Add missing SCSI loadparm attributes to /sys/firmware
Currently the loadparm is only supported for CCW IPL. But also for SCSI IPL it can be specified either on the HMC load panel respectively z/VM console or via diagnose 308. So fix this for SCSI and add the required sysfs attributes for reading the IPL loadparm and for setting the loadparm for re-IPL. With this patch the following two sysfs attributes are introduced: - /sys/firmware/ipl/loadparm (for system that have been IPLed from SCSI) - /sys/firmware/reipl/fcp/loadparm Because the loadparm is now available for SCSI and CCW it is moved now from "struct ipl_block_ccw" to the generic "struct ipl_list_hdr". Reviewed-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
-rw-r--r--arch/s390/include/asm/ipl.h8
-rw-r--r--arch/s390/kernel/ipl.c128
2 files changed, 89 insertions, 47 deletions
diff --git a/arch/s390/include/asm/ipl.h b/arch/s390/include/asm/ipl.h
index 2fcccc0c997c..c81661e756a0 100644
--- a/arch/s390/include/asm/ipl.h
+++ b/arch/s390/include/asm/ipl.h
@@ -17,12 +17,12 @@
17#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \ 17#define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
18 sizeof(struct ipl_block_fcp)) 18 sizeof(struct ipl_block_fcp))
19 19
20#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 8) 20#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 16)
21 21
22#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \ 22#define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
23 sizeof(struct ipl_block_ccw)) 23 sizeof(struct ipl_block_ccw))
24 24
25#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 8) 25#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 16)
26 26
27#define IPL_MAX_SUPPORTED_VERSION (0) 27#define IPL_MAX_SUPPORTED_VERSION (0)
28 28
@@ -38,10 +38,11 @@ struct ipl_list_hdr {
38 u8 pbt; 38 u8 pbt;
39 u8 flags; 39 u8 flags;
40 u16 reserved2; 40 u16 reserved2;
41 u8 loadparm[8];
41} __attribute__((packed)); 42} __attribute__((packed));
42 43
43struct ipl_block_fcp { 44struct ipl_block_fcp {
44 u8 reserved1[313-1]; 45 u8 reserved1[305-1];
45 u8 opt; 46 u8 opt;
46 u8 reserved2[3]; 47 u8 reserved2[3];
47 u16 reserved3; 48 u16 reserved3;
@@ -62,7 +63,6 @@ struct ipl_block_fcp {
62 offsetof(struct ipl_block_fcp, scp_data))) 63 offsetof(struct ipl_block_fcp, scp_data)))
63 64
64struct ipl_block_ccw { 65struct ipl_block_ccw {
65 u8 load_parm[8];
66 u8 reserved1[84]; 66 u8 reserved1[84];
67 u8 reserved2[2]; 67 u8 reserved2[2];
68 u16 devno; 68 u16 devno;
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 22aac5885ba2..39badb9ca0b3 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -455,22 +455,6 @@ DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
455DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long) 455DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
456 IPL_PARMBLOCK_START->ipl_info.fcp.br_lba); 456 IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
457 457
458static struct attribute *ipl_fcp_attrs[] = {
459 &sys_ipl_type_attr.attr,
460 &sys_ipl_device_attr.attr,
461 &sys_ipl_fcp_wwpn_attr.attr,
462 &sys_ipl_fcp_lun_attr.attr,
463 &sys_ipl_fcp_bootprog_attr.attr,
464 &sys_ipl_fcp_br_lba_attr.attr,
465 NULL,
466};
467
468static struct attribute_group ipl_fcp_attr_group = {
469 .attrs = ipl_fcp_attrs,
470};
471
472/* CCW ipl device attributes */
473
474static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj, 458static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
475 struct kobj_attribute *attr, char *page) 459 struct kobj_attribute *attr, char *page)
476{ 460{
@@ -487,6 +471,23 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
487static struct kobj_attribute sys_ipl_ccw_loadparm_attr = 471static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
488 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL); 472 __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
489 473
474static struct attribute *ipl_fcp_attrs[] = {
475 &sys_ipl_type_attr.attr,
476 &sys_ipl_device_attr.attr,
477 &sys_ipl_fcp_wwpn_attr.attr,
478 &sys_ipl_fcp_lun_attr.attr,
479 &sys_ipl_fcp_bootprog_attr.attr,
480 &sys_ipl_fcp_br_lba_attr.attr,
481 &sys_ipl_ccw_loadparm_attr.attr,
482 NULL,
483};
484
485static struct attribute_group ipl_fcp_attr_group = {
486 .attrs = ipl_fcp_attrs,
487};
488
489/* CCW ipl device attributes */
490
490static struct attribute *ipl_ccw_attrs_vm[] = { 491static struct attribute *ipl_ccw_attrs_vm[] = {
491 &sys_ipl_type_attr.attr, 492 &sys_ipl_type_attr.attr,
492 &sys_ipl_device_attr.attr, 493 &sys_ipl_device_attr.attr,
@@ -765,28 +766,10 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
765DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n", 766DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
766 reipl_block_fcp->ipl_info.fcp.devno); 767 reipl_block_fcp->ipl_info.fcp.devno);
767 768
768static struct attribute *reipl_fcp_attrs[] = {
769 &sys_reipl_fcp_device_attr.attr,
770 &sys_reipl_fcp_wwpn_attr.attr,
771 &sys_reipl_fcp_lun_attr.attr,
772 &sys_reipl_fcp_bootprog_attr.attr,
773 &sys_reipl_fcp_br_lba_attr.attr,
774 NULL,
775};
776
777static struct attribute_group reipl_fcp_attr_group = {
778 .attrs = reipl_fcp_attrs,
779};
780
781/* CCW reipl device attributes */
782
783DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
784 reipl_block_ccw->ipl_info.ccw.devno);
785
786static void reipl_get_ascii_loadparm(char *loadparm, 769static void reipl_get_ascii_loadparm(char *loadparm,
787 struct ipl_parameter_block *ibp) 770 struct ipl_parameter_block *ibp)
788{ 771{
789 memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN); 772 memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
790 EBCASC(loadparm, LOADPARM_LEN); 773 EBCASC(loadparm, LOADPARM_LEN);
791 loadparm[LOADPARM_LEN] = 0; 774 loadparm[LOADPARM_LEN] = 0;
792 strim(loadparm); 775 strim(loadparm);
@@ -821,13 +804,50 @@ static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
821 return -EINVAL; 804 return -EINVAL;
822 } 805 }
823 /* initialize loadparm with blanks */ 806 /* initialize loadparm with blanks */
824 memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN); 807 memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
825 /* copy and convert to ebcdic */ 808 /* copy and convert to ebcdic */
826 memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len); 809 memcpy(ipb->hdr.loadparm, buf, lp_len);
827 ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN); 810 ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
828 return len; 811 return len;
829} 812}
830 813
814/* FCP wrapper */
815static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
816 struct kobj_attribute *attr, char *page)
817{
818 return reipl_generic_loadparm_show(reipl_block_fcp, page);
819}
820
821static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
822 struct kobj_attribute *attr,
823 const char *buf, size_t len)
824{
825 return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
826}
827
828static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
829 __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
830 reipl_fcp_loadparm_store);
831
832static struct attribute *reipl_fcp_attrs[] = {
833 &sys_reipl_fcp_device_attr.attr,
834 &sys_reipl_fcp_wwpn_attr.attr,
835 &sys_reipl_fcp_lun_attr.attr,
836 &sys_reipl_fcp_bootprog_attr.attr,
837 &sys_reipl_fcp_br_lba_attr.attr,
838 &sys_reipl_fcp_loadparm_attr.attr,
839 NULL,
840};
841
842static struct attribute_group reipl_fcp_attr_group = {
843 .attrs = reipl_fcp_attrs,
844};
845
846/* CCW reipl device attributes */
847
848DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
849 reipl_block_ccw->ipl_info.ccw.devno);
850
831/* NSS wrapper */ 851/* NSS wrapper */
832static ssize_t reipl_nss_loadparm_show(struct kobject *kobj, 852static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
833 struct kobj_attribute *attr, char *page) 853 struct kobj_attribute *attr, char *page)
@@ -1125,11 +1145,10 @@ static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
1125 /* LOADPARM */ 1145 /* LOADPARM */
1126 /* check if read scp info worked and set loadparm */ 1146 /* check if read scp info worked and set loadparm */
1127 if (sclp_ipl_info.is_valid) 1147 if (sclp_ipl_info.is_valid)
1128 memcpy(ipb->ipl_info.ccw.load_parm, 1148 memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
1129 &sclp_ipl_info.loadparm, LOADPARM_LEN);
1130 else 1149 else
1131 /* read scp info failed: set empty loadparm (EBCDIC blanks) */ 1150 /* read scp info failed: set empty loadparm (EBCDIC blanks) */
1132 memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN); 1151 memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
1133 ipb->hdr.flags = DIAG308_FLAGS_LP_VALID; 1152 ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
1134 1153
1135 /* VM PARM */ 1154 /* VM PARM */
@@ -1251,9 +1270,16 @@ static int __init reipl_fcp_init(void)
1251 return rc; 1270 return rc;
1252 } 1271 }
1253 1272
1254 if (ipl_info.type == IPL_TYPE_FCP) 1273 if (ipl_info.type == IPL_TYPE_FCP) {
1255 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE); 1274 memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
1256 else { 1275 /*
1276 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1277 * is invalid in the SCSI IPL parameter block, so take it
1278 * always from sclp_ipl_info.
1279 */
1280 memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
1281 LOADPARM_LEN);
1282 } else {
1257 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN; 1283 reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
1258 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION; 1284 reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
1259 reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN; 1285 reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
@@ -1864,7 +1890,23 @@ static void __init shutdown_actions_init(void)
1864 1890
1865static int __init s390_ipl_init(void) 1891static int __init s390_ipl_init(void)
1866{ 1892{
1893 char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
1894
1867 sclp_get_ipl_info(&sclp_ipl_info); 1895 sclp_get_ipl_info(&sclp_ipl_info);
1896 /*
1897 * Fix loadparm: There are systems where the (SCSI) LOADPARM
1898 * returned by read SCP info is invalid (contains EBCDIC blanks)
1899 * when the system has been booted via diag308. In that case we use
1900 * the value from diag308, if available.
1901 *
1902 * There are also systems where diag308 store does not work in
1903 * case the system is booted from HMC. Fortunately in this case
1904 * READ SCP info provides the correct value.
1905 */
1906 if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 &&
1907 diag308_set_works)
1908 memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm,
1909 LOADPARM_LEN);
1868 shutdown_actions_init(); 1910 shutdown_actions_init();
1869 shutdown_triggers_init(); 1911 shutdown_triggers_init();
1870 return 0; 1912 return 0;