s390/ipl: Add missing SCSI loadparm attributes to /sys/firmware
authorMichael Holzheu <holzheu@linux.vnet.ibm.com>
Tue, 26 Aug 2014 15:51:08 +0000 (17:51 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 1 Sep 2014 07:56:29 +0000 (09:56 +0200)
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>
arch/s390/include/asm/ipl.h
arch/s390/kernel/ipl.c

index 2fcccc0c997cc3102dcb67e5ea2f60fc4f4200b2..c81661e756a0396bb8e90dee214492b154081d91 100644 (file)
 #define IPL_PARM_BLK_FCP_LEN (sizeof(struct ipl_list_hdr) + \
                              sizeof(struct ipl_block_fcp))
 
-#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 8)
+#define IPL_PARM_BLK0_FCP_LEN (sizeof(struct ipl_block_fcp) + 16)
 
 #define IPL_PARM_BLK_CCW_LEN (sizeof(struct ipl_list_hdr) + \
                              sizeof(struct ipl_block_ccw))
 
-#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 8)
+#define IPL_PARM_BLK0_CCW_LEN (sizeof(struct ipl_block_ccw) + 16)
 
 #define IPL_MAX_SUPPORTED_VERSION (0)
 
@@ -38,10 +38,11 @@ struct ipl_list_hdr {
        u8  pbt;
        u8  flags;
        u16 reserved2;
+       u8  loadparm[8];
 } __attribute__((packed));
 
 struct ipl_block_fcp {
-       u8  reserved1[313-1];
+       u8  reserved1[305-1];
        u8  opt;
        u8  reserved2[3];
        u16 reserved3;
@@ -62,7 +63,6 @@ struct ipl_block_fcp {
                                 offsetof(struct ipl_block_fcp, scp_data)))
 
 struct ipl_block_ccw {
-       u8  load_parm[8];
        u8  reserved1[84];
        u8  reserved2[2];
        u16 devno;
index 22aac5885ba23eca4590d9219aefc1fab34d9325..39badb9ca0b30c6b7b32ce720165e85c3c33319a 100644 (file)
@@ -455,22 +455,6 @@ DEFINE_IPL_ATTR_RO(ipl_fcp, bootprog, "%lld\n", (unsigned long long)
 DEFINE_IPL_ATTR_RO(ipl_fcp, br_lba, "%lld\n", (unsigned long long)
                   IPL_PARMBLOCK_START->ipl_info.fcp.br_lba);
 
-static struct attribute *ipl_fcp_attrs[] = {
-       &sys_ipl_type_attr.attr,
-       &sys_ipl_device_attr.attr,
-       &sys_ipl_fcp_wwpn_attr.attr,
-       &sys_ipl_fcp_lun_attr.attr,
-       &sys_ipl_fcp_bootprog_attr.attr,
-       &sys_ipl_fcp_br_lba_attr.attr,
-       NULL,
-};
-
-static struct attribute_group ipl_fcp_attr_group = {
-       .attrs = ipl_fcp_attrs,
-};
-
-/* CCW ipl device attributes */
-
 static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
                                     struct kobj_attribute *attr, char *page)
 {
@@ -487,6 +471,23 @@ static ssize_t ipl_ccw_loadparm_show(struct kobject *kobj,
 static struct kobj_attribute sys_ipl_ccw_loadparm_attr =
        __ATTR(loadparm, 0444, ipl_ccw_loadparm_show, NULL);
 
+static struct attribute *ipl_fcp_attrs[] = {
+       &sys_ipl_type_attr.attr,
+       &sys_ipl_device_attr.attr,
+       &sys_ipl_fcp_wwpn_attr.attr,
+       &sys_ipl_fcp_lun_attr.attr,
+       &sys_ipl_fcp_bootprog_attr.attr,
+       &sys_ipl_fcp_br_lba_attr.attr,
+       &sys_ipl_ccw_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group ipl_fcp_attr_group = {
+       .attrs = ipl_fcp_attrs,
+};
+
+/* CCW ipl device attributes */
+
 static struct attribute *ipl_ccw_attrs_vm[] = {
        &sys_ipl_type_attr.attr,
        &sys_ipl_device_attr.attr,
@@ -765,28 +766,10 @@ DEFINE_IPL_ATTR_RW(reipl_fcp, br_lba, "%lld\n", "%lld\n",
 DEFINE_IPL_ATTR_RW(reipl_fcp, device, "0.0.%04llx\n", "0.0.%llx\n",
                   reipl_block_fcp->ipl_info.fcp.devno);
 
-static struct attribute *reipl_fcp_attrs[] = {
-       &sys_reipl_fcp_device_attr.attr,
-       &sys_reipl_fcp_wwpn_attr.attr,
-       &sys_reipl_fcp_lun_attr.attr,
-       &sys_reipl_fcp_bootprog_attr.attr,
-       &sys_reipl_fcp_br_lba_attr.attr,
-       NULL,
-};
-
-static struct attribute_group reipl_fcp_attr_group = {
-       .attrs = reipl_fcp_attrs,
-};
-
-/* CCW reipl device attributes */
-
-DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
-       reipl_block_ccw->ipl_info.ccw.devno);
-
 static void reipl_get_ascii_loadparm(char *loadparm,
                                     struct ipl_parameter_block *ibp)
 {
-       memcpy(loadparm, ibp->ipl_info.ccw.load_parm, LOADPARM_LEN);
+       memcpy(loadparm, ibp->hdr.loadparm, LOADPARM_LEN);
        EBCASC(loadparm, LOADPARM_LEN);
        loadparm[LOADPARM_LEN] = 0;
        strim(loadparm);
@@ -821,13 +804,50 @@ static ssize_t reipl_generic_loadparm_store(struct ipl_parameter_block *ipb,
                return -EINVAL;
        }
        /* initialize loadparm with blanks */
-       memset(ipb->ipl_info.ccw.load_parm, ' ', LOADPARM_LEN);
+       memset(ipb->hdr.loadparm, ' ', LOADPARM_LEN);
        /* copy and convert to ebcdic */
-       memcpy(ipb->ipl_info.ccw.load_parm, buf, lp_len);
-       ASCEBC(ipb->ipl_info.ccw.load_parm, LOADPARM_LEN);
+       memcpy(ipb->hdr.loadparm, buf, lp_len);
+       ASCEBC(ipb->hdr.loadparm, LOADPARM_LEN);
        return len;
 }
 
+/* FCP wrapper */
+static ssize_t reipl_fcp_loadparm_show(struct kobject *kobj,
+                                      struct kobj_attribute *attr, char *page)
+{
+       return reipl_generic_loadparm_show(reipl_block_fcp, page);
+}
+
+static ssize_t reipl_fcp_loadparm_store(struct kobject *kobj,
+                                       struct kobj_attribute *attr,
+                                       const char *buf, size_t len)
+{
+       return reipl_generic_loadparm_store(reipl_block_fcp, buf, len);
+}
+
+static struct kobj_attribute sys_reipl_fcp_loadparm_attr =
+       __ATTR(loadparm, S_IRUGO | S_IWUSR, reipl_fcp_loadparm_show,
+                                           reipl_fcp_loadparm_store);
+
+static struct attribute *reipl_fcp_attrs[] = {
+       &sys_reipl_fcp_device_attr.attr,
+       &sys_reipl_fcp_wwpn_attr.attr,
+       &sys_reipl_fcp_lun_attr.attr,
+       &sys_reipl_fcp_bootprog_attr.attr,
+       &sys_reipl_fcp_br_lba_attr.attr,
+       &sys_reipl_fcp_loadparm_attr.attr,
+       NULL,
+};
+
+static struct attribute_group reipl_fcp_attr_group = {
+       .attrs = reipl_fcp_attrs,
+};
+
+/* CCW reipl device attributes */
+
+DEFINE_IPL_ATTR_RW(reipl_ccw, device, "0.0.%04llx\n", "0.0.%llx\n",
+       reipl_block_ccw->ipl_info.ccw.devno);
+
 /* NSS wrapper */
 static ssize_t reipl_nss_loadparm_show(struct kobject *kobj,
                                       struct kobj_attribute *attr, char *page)
@@ -1125,11 +1145,10 @@ static void reipl_block_ccw_fill_parms(struct ipl_parameter_block *ipb)
        /* LOADPARM */
        /* check if read scp info worked and set loadparm */
        if (sclp_ipl_info.is_valid)
-               memcpy(ipb->ipl_info.ccw.load_parm,
-                               &sclp_ipl_info.loadparm, LOADPARM_LEN);
+               memcpy(ipb->hdr.loadparm, &sclp_ipl_info.loadparm, LOADPARM_LEN);
        else
                /* read scp info failed: set empty loadparm (EBCDIC blanks) */
-               memset(ipb->ipl_info.ccw.load_parm, 0x40, LOADPARM_LEN);
+               memset(ipb->hdr.loadparm, 0x40, LOADPARM_LEN);
        ipb->hdr.flags = DIAG308_FLAGS_LP_VALID;
 
        /* VM PARM */
@@ -1251,9 +1270,16 @@ static int __init reipl_fcp_init(void)
                return rc;
        }
 
-       if (ipl_info.type == IPL_TYPE_FCP)
+       if (ipl_info.type == IPL_TYPE_FCP) {
                memcpy(reipl_block_fcp, IPL_PARMBLOCK_START, PAGE_SIZE);
-       else {
+               /*
+                * Fix loadparm: There are systems where the (SCSI) LOADPARM
+                * is invalid in the SCSI IPL parameter block, so take it
+                * always from sclp_ipl_info.
+                */
+               memcpy(reipl_block_fcp->hdr.loadparm, sclp_ipl_info.loadparm,
+                      LOADPARM_LEN);
+       } else {
                reipl_block_fcp->hdr.len = IPL_PARM_BLK_FCP_LEN;
                reipl_block_fcp->hdr.version = IPL_PARM_BLOCK_VERSION;
                reipl_block_fcp->hdr.blk0_len = IPL_PARM_BLK0_FCP_LEN;
@@ -1864,7 +1890,23 @@ static void __init shutdown_actions_init(void)
 
 static int __init s390_ipl_init(void)
 {
+       char str[8] = {0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40};
+
        sclp_get_ipl_info(&sclp_ipl_info);
+       /*
+        * Fix loadparm: There are systems where the (SCSI) LOADPARM
+        * returned by read SCP info is invalid (contains EBCDIC blanks)
+        * when the system has been booted via diag308. In that case we use
+        * the value from diag308, if available.
+        *
+        * There are also systems where diag308 store does not work in
+        * case the system is booted from HMC. Fortunately in this case
+        * READ SCP info provides the correct value.
+        */
+       if (memcmp(sclp_ipl_info.loadparm, str, sizeof(str)) == 0 &&
+           diag308_set_works)
+               memcpy(sclp_ipl_info.loadparm, ipl_block.hdr.loadparm,
+                      LOADPARM_LEN);
        shutdown_actions_init();
        shutdown_triggers_init();
        return 0;
This page took 0.05242 seconds and 5 git commands to generate.