diff options
-rw-r--r-- | iprconfig.8 | 5 | ||||
-rw-r--r-- | iprconfig.c | 76 | ||||
-rw-r--r-- | iprlib.c | 34 | ||||
-rw-r--r-- | 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 34721ca..bb3a4d8 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); @@ -18496,6 +18551,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" }, @@ -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; @@ -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 *); |