summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--iprconfig.85
-rw-r--r--iprconfig.c76
-rw-r--r--iprlib.c34
-rw-r--r--iprlib.h1
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" },
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 *);