show-ucode-levels prints all IPR adapters and devices, along with their
current firmware levels as well as the latest available version found on
disk which could be updated to.

Signed-off-by: Gabriel Krisman Bertazi <kris...@linux.vnet.ibm.com>
---
 iprconfig.8 |  5 ++++
 iprconfig.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 iprlib.c    | 34 +++++++++++++++++++++++++++
 iprlib.h    |  1 +
 4 files changed, 106 insertions(+), 10 deletions(-)

diff --git a/iprconfig.8 b/iprconfig.8
index 2282fac..3f07532 100644
--- a/iprconfig.8
+++ b/iprconfig.8
@@ -337,6 +337,11 @@ Show the microcode level that is currently loaded on the 
specified device.
 Note: The device specified may be the sg device associated with an IOA,
 in which case the IOA's microcode level will be shown.
 .TP
+.B show-ucode-levels
+.br
+Show the microcode level that is currently loaded for every device and
+adapter in the system.
+.TP
 .B query-format-timeout [device]
 .br
 Show the current format timeout to be used when formatting the specified disk.
diff --git a/iprconfig.c b/iprconfig.c
index ee7bb9d..4ab7562 100644
--- a/iprconfig.c
+++ b/iprconfig.c
@@ -125,7 +125,7 @@ struct special_status {
 
 char *print_device(struct ipr_dev *, char *, char *, int);
 int display_menu(ITEM **, int, int, int **);
-char *__print_device(struct ipr_dev *, char *, char *, int, int, int, int, 
int, int, int, int, int, int, int, int);
+char *__print_device(struct ipr_dev *, char *, char *, int, int, int, int, 
int, int, int, int, int, int, int, int, int, int, int);
 static char *print_path_details(struct ipr_dev *, char *);
 static int get_drive_phy_loc(struct ipr_ioa *ioa);
 
@@ -1124,7 +1124,10 @@ static char *status_hdr[] = {
                "Name   Platform Location          Description                  
Status",
                "OPT Name   PCI/Host/Resource Path                   Serial 
Number Status",
                "OPT Name   Physical Location                        Production 
ID    Status",
-               "Name   Physical Location                        Serial Number 
Status"};
+               "Name   Physical Location                        Serial Number 
Status",
+               "Name   PCI/SCSI Location          Vendor   Product ID          
Current    Available",
+               "OPT Name   PCI/SCSI Location          Vendor   Product ID      
    Current    Available",
+};
 
 static char *status_sep[] = {
                "--- ------ -------------------------- -------- 
------------------- -----------------",
@@ -1142,6 +1145,8 @@ static char *status_sep[] = {
                "--- ------ ---------------------------------------- 
------------- ------------",
                "--- ------ ---------------------------------------- 
---------------- ------------",
                "------ ---------------------------------------- ------------- 
------------",
+               "-----  ----------------------     -------- ----------------    
---------  ----------",
+               "--- -----  ----------------------     -------- 
----------------    ---------  ----------",
 };
 
 /**
@@ -8286,8 +8291,8 @@ int path_status(i_container * i_con)
                        continue;
 
                for_each_disk(ioa, dev) {
-                       buffer[0] = __print_device(dev, buffer[0], "%1", 1, 1, 
1, 0, 0, 1, 0, 1, 0 ,0, 0, 0);
-                       buffer[1] = __print_device(dev, buffer[1], "%1", 1, 1, 
0, 0, 0, 0, 0, 1, 0 ,0, 0, 0);
+                       buffer[0] = __print_device(dev, buffer[0], "%1", 1, 1, 
1, 0, 0, 1, 0, 1, 0 ,0, 0, 0, 0, 0, 0);
+                       buffer[1] = __print_device(dev, buffer[1], "%1", 1, 1, 
0, 0, 0, 0, 0, 1, 0 ,0, 0, 0, 0, 0, 0);
                        i_con = add_i_con(i_con, "\0", dev);
                        num_devs++;
                }
@@ -12864,7 +12869,8 @@ static char *print_path_details(struct ipr_dev *dev, 
char *body)
 char *__print_device(struct ipr_dev *dev, char *body, char *option,
                     int sd, int sg, int vpd, int percent, int indent,
                     int res_path, int ra, int path_status,
-                    int hw_loc, int conc_main, int ioa_flag, int serial_num)
+                    int hw_loc, int conc_main, int ioa_flag, int serial_num,
+                    int ucode, int skip_status, int skip_vset)
 {
        u16 len = 0;
        struct scsi_dev_data *scsi_dev_data = dev->scsi_dev_data;
@@ -12884,6 +12890,9 @@ char *__print_device(struct ipr_dev *dev, char *body, 
char *option,
        if (!ioa)
                return body;
 
+       if (skip_vset && ipr_is_volume_set (dev))
+               return body;
+
        if (ioa_flag)
                ioa_phy_loc = dev->ioa;
 
@@ -13201,8 +13210,23 @@ char *__print_device(struct ipr_dev *dev, char *body, 
char *option,
                }
        }
 
-       get_status(dev, buf, percent, path_status);
-       sprintf(body + len, "%s\n", buf);
+       if (ucode) {
+               int cur_ulevel = get_fw_version(dev);
+               int newest_ulevel = get_latest_fw_image_version(dev);
+               char updatable;
+               newest_ulevel = (newest_ulevel < 0) ?
+                       cur_ulevel:newest_ulevel;
+               updatable = (cur_ulevel < newest_ulevel) ? '*':' ';
+               len +=  sprintf(body + len, "%-10X %X%c", cur_ulevel,
+                               newest_ulevel, updatable);
+       }
+
+       if (!skip_status) {
+               get_status(dev, buf, percent, path_status);
+               len += sprintf(body + len, "%s", buf);
+       }
+       sprintf(body + len, "\n");
+
        return body;
 }
 
@@ -13230,10 +13254,14 @@ char *__print_device(struct ipr_dev *dev, char *body, 
char *option,
  * 7: print sd, the second resource adress(sis32)/resource path(sis64), dev VPD
  * 8: print sg, pci/host/resource path, serial number, status
  * 9: print sg, physical location, production id, status
+ * 10: print sd, pci/host/resource vendor, product id, ucode version, 
available ucode
  */
 char *print_device(struct ipr_dev *dev, char *body, char *option, int type)
 {
        int sd, sg, vpd, percent, indent, res_path, hw_loc, conc_main, 
ioa_flag, serial_num;
+       int ucode = 0;
+       int skip_status = 0;
+       int skip_vset = 0;
 
        sd = sg = vpd = percent = indent = res_path = hw_loc = conc_main = 
ioa_flag = serial_num = 0;
 
@@ -13282,8 +13310,18 @@ char *print_device(struct ipr_dev *dev, char *body, 
char *option, int type)
                        res_path = 0;
                vpd = 1;
        }
+       if (type == 10) {
+               ucode = 1;
+               sg = 1;
+               vpd = 1;
+               skip_status = 1;
+               skip_vset = 1;
+       }
 
-       return __print_device(dev, body, option, sd, sg, vpd, percent, indent, 
res_path, type&1, 0, hw_loc, conc_main, ioa_flag, serial_num);
+       return __print_device(dev, body, option, sd, sg, vpd, percent,
+                             indent, res_path, type&1, 0, hw_loc,
+                             conc_main, ioa_flag, serial_num, ucode,
+                             skip_status, skip_vset);
 }
 
 /**
@@ -13935,7 +13973,7 @@ static void printf_device(struct ipr_dev *dev, int type)
 static void __printf_device(struct ipr_dev *dev, int sd, int sg, int vpd,
                            int percent, int indent, int res_path)
 {
-       char *buf = __print_device(dev, NULL, NULL, sd, sg, vpd, percent, 
indent, res_path, 0, 0, 0, 0, 0, 0);
+       char *buf = __print_device(dev, NULL, NULL, sd, sg, vpd, percent, 
indent, res_path, 0, 0, 0, 0, 0, 0, 0, 0 ,0);
        if (buf) {
                printf("%s", buf);
                free(buf);
@@ -15116,6 +15154,23 @@ static int update_ucode_cmd(char **args, int num_args)
 }
 
 /**
+ * show_ucode_levels - List microcode level of every device and adapter
+ * @args:              argument vector
+ * @num_args:          number of arguments
+ *
+ * Returns:
+ *   0 if success / non-zero on failure
+ **/
+static int show_ucode_levels(char **args, int num_args)
+{
+       struct ipr_ioa *ioa;
+       printf("%s\n%s\n", status_hdr[15], status_sep[15]);
+       for_each_ioa(ioa)
+               printf_ioa(ioa, 10);
+       return 0;
+}
+
+/**
  * disrupt_device_cmd -
  * @args:              argument vector
  * @num_args:          number of arguments
@@ -15272,7 +15327,7 @@ static int query_path_details(char **args, int num_args)
  **/
 static void printf_path_status(struct ipr_dev *dev)
 {
-       char *buf = __print_device(dev, NULL, NULL, 1, 1, 1, 0, 0, 0, 0, 1, 0, 
0, 0, 0);
+       char *buf = __print_device(dev, NULL, NULL, 1, 1, 1, 0, 0, 0, 0, 1, 0, 
0, 0, 0, 0, 0, 0);
        if (buf) {
                printf("%s", buf);
                free(buf);
@@ -18494,6 +18549,7 @@ static const struct {
        { "raid-rebuild",                       1, 0, 1, raid_rebuild_cmd, 
"sg6" },
        { "disrupt-device",                     1, 0, 1, disrupt_device_cmd, 
"sg6" },
        { "update-ucode",                       2, 0, 2, update_ucode_cmd, "sg5 
/root/ucode.bin" },
+       { "show-ucode-levels",                  0, 0, 0, show_ucode_levels, "" 
},
        { "set-format-timeout",                 2, 0, 2, set_format_timeout, 
"sg6 4" },
        { "set-qdepth",                         2, 0, 2, set_qdepth, "sda 16" },
        { "set-tcq-enable",                     2, 0, 2, set_tcq_enable, "sda 
0" },
diff --git a/iprlib.c b/iprlib.c
index 9b0b4a4..94bcdca 100644
--- a/iprlib.c
+++ b/iprlib.c
@@ -8625,6 +8625,40 @@ int get_ses_firmware_image_list(struct ipr_dev *dev,
        return len;
 }
 
+
+/**
+ * get_firmware_image_list - Common interface to find version of the
+ * latest microcode image found in the filesystem.
+ *
+ * @dev:               Device
+ *
+ * Returns:
+ *   0 if success / non-zero on failure
+ **/
+int get_latest_fw_image_version(struct ipr_dev *dev)
+{
+       struct ipr_fw_images *fw = NULL;
+       u32 version = 0;
+
+       if (!dev)
+               return -ENODEV;
+
+       if (dev->scsi_dev_data->type == IPR_TYPE_ADAPTER)
+               get_ioa_firmware_image_list(dev->ioa, &fw);
+       else if (ipr_is_ses(dev))
+               get_ses_firmware_image_list(dev, &fw);
+       else if (ipr_is_gscsi(dev) || ipr_is_af_dasd_device(dev))
+               get_dasd_firmware_image_list(dev, &fw);
+
+       if (!fw)
+               return -EINVAL;
+
+       version = fw->version;
+       free(fw);
+
+       return version;
+}
+
 struct ipr_ioa_desc {
        u16 type;
        const char *desc;
diff --git a/iprlib.h b/iprlib.h
index e66ea47..9c09cba 100644
--- a/iprlib.h
+++ b/iprlib.h
@@ -2701,6 +2701,7 @@ int ipr_query_dasd_timeouts(struct ipr_dev *, struct 
ipr_query_dasd_timeouts *);
 int get_ioa_firmware_image_list(struct ipr_ioa *, struct ipr_fw_images **);
 int get_dasd_firmware_image_list(struct ipr_dev *, struct ipr_fw_images **);
 int get_ses_firmware_image_list(struct ipr_dev *, struct ipr_fw_images **);
+int get_latest_fw_image_version(struct ipr_dev *);
 int ipr_update_ioa_fw(struct ipr_ioa *, struct ipr_fw_images *, int);
 int ipr_update_disk_fw(struct ipr_dev *, struct ipr_fw_images *, int);
 int ipr_init_dev(struct ipr_dev *);
-- 
2.1.0


------------------------------------------------------------------------------
_______________________________________________
Iprdd-devel mailing list
Iprdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iprdd-devel

Reply via email to