From 0858eccf86e9b3611d711717ec65a042f5c7ff9f Mon Sep 17 00:00:00 2001
From: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Date: Wed, 19 Nov 2014 13:53:29 +0100
Subject: [PATCH 4/5] imsm: detail-platform improvements

Print platform details per OROM, not per controller, differentiate
RST(e) platforms from legacy IMSM, print NVMe device paths, adjust port
printing to newer sysfs path.

Signed-off-by: Artur Paszkiewicz <artur.paszkiewicz@intel.com>
Signed-off-by: Pawel Baldysiak <pawel.baldysiak@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
---
 platform-intel.c |   26 +++++++++------
 platform-intel.h |   23 +++++++++++++
 super-intel.c    |   93 +++++++++++++++++++++++++++++++++++++------------------
 3 files changed, 103 insertions(+), 39 deletions(-)

--- mdadm-3.3.1.orig/platform-intel.c
+++ mdadm-3.3.1/platform-intel.c
@@ -134,6 +134,16 @@ struct sys_dev *find_driver_devices(cons
 static struct sys_dev *intel_devices=NULL;
 static time_t valid_time = 0;
 
+struct sys_dev *device_by_id(__u16 device_id)
+{
+	struct sys_dev *iter;
+
+	for (iter = intel_devices; iter != NULL; iter = iter->next)
+		if (iter->dev_id == device_id)
+			return iter;
+	return NULL;
+}
+
 static int devpath_to_ll(const char *dev_path, const char *entry, unsigned long long *val)
 {
 	char path[strlen(dev_path) + strlen(entry) + 2];
@@ -219,18 +229,13 @@ struct pciExpDataStructFormat {
 	__u16 devListOffset;
 } __attribute__ ((packed));
 
-struct devid_list {
-	__u16 devid;
-	struct devid_list *next;
-};
-
-struct orom_entry {
-	struct imsm_orom orom;
-	struct devid_list *devid_list;
-};
-
 static struct orom_entry oroms[SYS_DEV_MAX];
 
+const struct orom_entry *get_oroms(void)
+{
+	return (const struct orom_entry *)&oroms;
+}
+
 const struct imsm_orom *get_orom_by_device_id(__u16 dev_id)
 {
 	int i;
@@ -529,6 +534,7 @@ const struct imsm_orom *find_imsm_nvme(s
 			.vpa = IMSM_OROM_VOLUMES_PER_ARRAY,
 			.vphba = IMSM_OROM_TOTAL_DISKS_NVME / 2 * IMSM_OROM_VOLUMES_PER_ARRAY,
 			.attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK,
+			.driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem
 		};
 		nvme_orom = add_orom(&nvme_orom_compat);
 	}
--- mdadm-3.3.1.orig/platform-intel.h
+++ mdadm-3.3.1/platform-intel.h
@@ -173,6 +173,17 @@ static inline int fls(int x)
 	return r;
 }
 
+static inline int imsm_orom_is_enterprise(const struct imsm_orom *orom)
+{
+	return !!(orom->driver_features & IMSM_OROM_CAPABILITIES_EnterpriseSystem);
+}
+
+static inline int imsm_orom_is_nvme(const struct imsm_orom *orom)
+{
+	return memcmp(orom->signature, IMSM_NVME_OROM_COMPAT_SIGNATURE,
+			sizeof(orom->signature)) == 0;
+}
+
 enum sys_dev_type {
 	SYS_DEV_UNKNOWN = 0,
 	SYS_DEV_SAS,
@@ -194,6 +205,16 @@ struct efi_guid {
 	__u8 b[16];
 };
 
+struct devid_list {
+	__u16 devid;
+	struct devid_list *next;
+};
+
+struct orom_entry {
+	struct imsm_orom orom;
+	struct devid_list *devid_list;
+};
+
 static inline char *guid_str(char *buf, struct efi_guid guid)
 {
 	sprintf(buf, "%02x%02x%02x%02x-%02x%02x-%02x%02x-"
@@ -215,4 +236,6 @@ int devt_attached_to_hba(dev_t dev, cons
 char *devt_to_devpath(dev_t dev);
 int path_attached_to_hba(const char *disk_path, const char *hba_path);
 const char *get_sys_dev_type(enum sys_dev_type);
+const struct orom_entry * get_oroms(void);
 const struct imsm_orom *get_orom_by_device_id(__u16 device_id);
+struct sys_dev *device_by_id(__u16 device_id);
--- mdadm-3.3.1.orig/super-intel.c
+++ mdadm-3.3.1/super-intel.c
@@ -1709,7 +1709,8 @@ static int ahci_enumerate_ports(const ch
 			break;
 		}
 		*c = '\0';
-		if (sscanf(&path[hba_len], "host%d", &port) == 1)
+		if ((sscanf(&path[hba_len], "ata%d", &port) == 1) ||
+		   ((sscanf(&path[hba_len], "host%d", &port) == 1)))
 			port -= host_base;
 		else {
 			if (verbose > 0) {
@@ -1768,6 +1769,8 @@ static void print_found_intel_controller
 			fprintf(stderr, "SATA ");
 		else if (elem->type == SYS_DEV_SAS)
 			fprintf(stderr, "SAS ");
+		else if (elem->type == SYS_DEV_NVME)
+			fprintf(stderr, "NVMe ");
 		fprintf(stderr, "RAID controller");
 		if (elem->pci_id)
 			fprintf(stderr, " at %s", elem->pci_id);
@@ -1789,7 +1792,8 @@ static int ahci_get_port_count(const cha
 	for (ent = readdir(dir); ent; ent = readdir(dir)) {
 		int host;
 
-		if (sscanf(ent->d_name, "host%d", &host) != 1)
+		if ((sscanf(ent->d_name, "ata%d", &host) != 1) &&
+		   ((sscanf(ent->d_name, "host%d", &host) != 1)))
 			continue;
 		if (*port_count == 0)
 			host_base = host;
@@ -1805,9 +1809,15 @@ static int ahci_get_port_count(const cha
 
 static void print_imsm_capability(const struct imsm_orom *orom)
 {
-	printf("       Platform : Intel(R) Matrix Storage Manager\n");
-	printf("        Version : %d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
-	       orom->hotfix_ver, orom->build);
+	printf("       Platform : Intel(R) ");
+	if (orom->capabilities == 0 && orom->driver_features == 0)
+		printf("Matrix Storage Manager\n");
+	else
+		printf("Rapid Storage Technology%s\n",
+			imsm_orom_is_enterprise(orom) ? " enterprise" : "");
+	if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
+		printf("        Version : %d.%d.%d.%d\n", orom->major_ver,
+				orom->minor_ver, orom->hotfix_ver, orom->build);
 	printf("    RAID Levels :%s%s%s%s%s\n",
 	       imsm_orom_has_raid0(orom) ? " raid0" : "",
 	       imsm_orom_has_raid1(orom) ? " raid1" : "",
@@ -1836,16 +1846,18 @@ static void print_imsm_capability(const
 	printf("      2TB disks :%s supported\n",
 	       (orom->attr & IMSM_OROM_ATTR_2TB_DISK)?"":" not");
 	printf("      Max Disks : %d\n", orom->tds);
-	printf("    Max Volumes : %d per array, %d per controller\n",
-	       orom->vpa, orom->vphba);
+	printf("    Max Volumes : %d per array, %d per %s\n",
+	       orom->vpa, orom->vphba,
+	       imsm_orom_is_nvme(orom) ? "platform" : "controller");
 	return;
 }
 
 static void print_imsm_capability_export(const struct imsm_orom *orom)
 {
 	printf("MD_FIRMWARE_TYPE=imsm\n");
-	printf("IMSM_VERSION=%d.%d.%d.%d\n",orom->major_ver, orom->minor_ver,
-			orom->hotfix_ver, orom->build);
+	if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build)
+		printf("IMSM_VERSION=%d.%d.%d.%d\n", orom->major_ver, orom->minor_ver,
+				orom->hotfix_ver, orom->build);
 	printf("IMSM_SUPPORTED_RAID_LEVELS=%s%s%s%s%s\n",
 			imsm_orom_has_raid0(orom) ? "raid0 " : "",
 			imsm_orom_has_raid1(orom) ? "raid1 " : "",
@@ -1889,7 +1901,6 @@ static int detail_platform_imsm(int verb
 	 * platform capabilities.  If raid support is disabled in the BIOS the
 	 * option-rom capability structure will not be available.
 	 */
-	const struct imsm_orom *orom;
 	struct sys_dev *list, *hba;
 	int host_base = 0;
 	int port_count = 0;
@@ -1922,15 +1933,42 @@ static int detail_platform_imsm(int verb
 		print_found_intel_controllers(list);
 
 	for (hba = list; hba; hba = hba->next) {
-		if (controller_path && (compare_paths(hba->path,controller_path) != 0))
+		if (controller_path && (compare_paths(hba->path, controller_path) != 0))
 			continue;
-		orom = find_imsm_capability(hba);
-		if (!orom)
+		if (!find_imsm_capability(hba)) {
 			pr_err("imsm capabilities not found for controller: %s (type %s)\n",
 				hba->path, get_sys_dev_type(hba->type));
-		else {
-			result = 0;
-			print_imsm_capability(orom);
+			continue;
+		}
+		result = 0;
+	}
+
+	if (controller_path && result == 1) {
+		pr_err("no active Intel(R) RAID controller found under %s\n",
+				controller_path);
+		return result;
+	}
+
+	const struct orom_entry *oroms = get_oroms();
+	int i;
+
+	for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++) {
+		print_imsm_capability(&oroms[i].orom);
+
+		if (imsm_orom_is_nvme(&oroms[i].orom)) {
+			for (hba = list; hba; hba = hba->next) {
+				if (hba->type == SYS_DEV_NVME)
+					printf("    NVMe Device : %s\n", hba->path);
+			}
+			continue;
+		}
+
+		struct devid_list *devid;
+		for (devid = oroms[i].devid_list; devid; devid = devid->next) {
+			hba = device_by_id(devid->devid);
+			if (!hba)
+				continue;
+
 			printf(" I/O Controller : %s (%s)\n",
 				hba->path, get_sys_dev_type(hba->type));
 			if (hba->type == SYS_DEV_SATA) {
@@ -1943,18 +1981,14 @@ static int detail_platform_imsm(int verb
 				}
 			}
 		}
+		printf("\n");
 	}
 
-	if (controller_path && result == 1)
-		pr_err("no active Intel(R) RAID "
-				"controller found under %s\n",controller_path);
-
 	return result;
 }
 
 static int export_detail_platform_imsm(int verbose, char *controller_path)
 {
-	const struct imsm_orom *orom;
 	struct sys_dev *list, *hba;
 	int result=1;
 
@@ -1969,17 +2003,18 @@ static int export_detail_platform_imsm(i
 	for (hba = list; hba; hba = hba->next) {
 		if (controller_path && (compare_paths(hba->path,controller_path) != 0))
 			continue;
-		orom = find_imsm_capability(hba);
-		if (!orom) {
-			if (verbose > 0)
-				pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n",hba->path);
-		}
-		else {
-			print_imsm_capability_export(orom);
+		if (!find_imsm_capability(hba) && verbose > 0)
+			pr_err("IMSM_DETAIL_PLATFORM_ERROR=NO_IMSM_CAPABLE_DEVICE_UNDER_%s\n", hba->path);
+		else
 			result = 0;
-		}
 	}
 
+	const struct orom_entry *oroms = get_oroms();
+	int i;
+
+	for (i = 0; i < SYS_DEV_MAX && oroms[i].devid_list; i++)
+		print_imsm_capability_export(&oroms[i].orom);
+
 	return result;
 }
 
