[PATCH] imsm: Add reading vmd register for finding imsm capability

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently mdadm does not find imsm capability when running inside VM.
This patch adds the possibility to read from vmd register and check for
capability, effectively allowing to use mdadm with imsm inside virtual machines.

Additionally refactor find_imsm_capability() to make assignments in new
lines.

Signed-off-by: Mateusz Grzonka <mateusz.grzonka@xxxxxxxxx>
---
 platform-intel.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++-
 platform-intel.h |  11 ++++-
 super-intel.c    |  11 +++--
 3 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/platform-intel.c b/platform-intel.c
index 757f0b1b..888a4f66 100644
--- a/platform-intel.c
+++ b/platform-intel.c
@@ -688,6 +688,106 @@ const struct imsm_orom *find_imsm_nvme(struct sys_dev *hba)
 	return &nvme_orom->orom;
 }
 
+#define VMD_REGISTER_OFFSET		0x3FC
+#define VMD_REGISTER_SKU_SHIFT		1
+#define VMD_REGISTER_SKU_MASK		(0x00000007)
+#define VMD_REGISTER_SKU_PREMIUM	2
+#define MD_REGISTER_VER_MAJOR_SHIFT	4
+#define MD_REGISTER_VER_MAJOR_MASK	(0x0000000F)
+#define MD_REGISTER_VER_MINOR_SHIFT	8
+#define MD_REGISTER_VER_MINOR_MASK	(0x0000000F)
+
+/*
+ * read_vmd_register() - Reads VMD register and writes contents to buff ptr
+ * @buff: buffer for vmd register data, should be the size of uint32_t
+ *
+ * Return: 0 on success, 1 on error
+ */
+int read_vmd_register(uint32_t *buff, struct sys_dev *hba)
+{
+	int fd;
+	char vmd_pci_config_path[PATH_MAX];
+
+	if (!vmd_domain_to_controller(hba, vmd_pci_config_path))
+		return 1;
+
+	strncat(vmd_pci_config_path, "/config", PATH_MAX - strnlen(vmd_pci_config_path, PATH_MAX));
+
+	fd = open(vmd_pci_config_path, O_RDONLY);
+	if (fd < 0)
+		return 1;
+
+	if (pread(fd, buff, sizeof(uint32_t), VMD_REGISTER_OFFSET) != sizeof(uint32_t)) {
+		close(fd);
+		return 1;
+	}
+	close(fd);
+	return 0;
+}
+
+/*
+ * add_vmd_orom() - Adds VMD orom cap to orom list, writes orom_entry ptr into vmd_orom
+ * @vmd_orom: pointer to orom entry pointer
+ *
+ * Return: 0 on success, 1 on error
+ */
+int add_vmd_orom(struct orom_entry **vmd_orom, struct sys_dev *hba)
+{
+	uint8_t sku;
+	uint32_t vmd_register_data;
+	struct imsm_orom vmd_orom_cap = {
+		.signature = IMSM_VMD_OROM_COMPAT_SIGNATURE,
+		.sss = IMSM_OROM_SSS_4kB | IMSM_OROM_SSS_8kB |
+					IMSM_OROM_SSS_16kB | IMSM_OROM_SSS_32kB |
+					IMSM_OROM_SSS_64kB | IMSM_OROM_SSS_128kB,
+		.dpa = IMSM_OROM_DISKS_PER_ARRAY_NVME,
+		.tds = IMSM_OROM_TOTAL_DISKS_VMD,
+		.vpa = IMSM_OROM_VOLUMES_PER_ARRAY,
+		.vphba = IMSM_OROM_VOLUMES_PER_HBA_VMD,
+		.attr = IMSM_OROM_ATTR_2TB | IMSM_OROM_ATTR_2TB_DISK,
+		.driver_features = IMSM_OROM_CAPABILITIES_EnterpriseSystem |
+				   IMSM_OROM_CAPABILITIES_TPV
+	};
+
+	if (read_vmd_register(&vmd_register_data, hba) != 0)
+		return 1;
+
+	sku = (uint8_t)((vmd_register_data >> VMD_REGISTER_SKU_SHIFT) &
+		VMD_REGISTER_SKU_MASK);
+
+	if (sku == VMD_REGISTER_SKU_PREMIUM)
+		vmd_orom_cap.rlc = IMSM_OROM_RLC_RAID0 | IMSM_OROM_RLC_RAID1 |
+				   IMSM_OROM_RLC_RAID10 | IMSM_OROM_RLC_RAID5;
+	else
+		vmd_orom_cap.rlc = IMSM_OROM_RLC_RAID_CNG;
+
+	vmd_orom_cap.major_ver = (uint8_t)
+		((vmd_register_data >> MD_REGISTER_VER_MAJOR_SHIFT) &
+			MD_REGISTER_VER_MAJOR_MASK);
+	vmd_orom_cap.minor_ver = (uint8_t)
+		((vmd_register_data >> MD_REGISTER_VER_MINOR_SHIFT) &
+			MD_REGISTER_VER_MINOR_MASK);
+
+	*vmd_orom = add_orom(&vmd_orom_cap);
+
+	return 0;
+}
+
+const struct imsm_orom *find_imsm_vmd(struct sys_dev *hba)
+{
+	static struct orom_entry *vmd_orom;
+
+	if (hba->type != SYS_DEV_VMD)
+		return NULL;
+
+	if (!vmd_orom && add_vmd_orom(&vmd_orom, hba) != 0)
+		return NULL;
+
+	add_orom_device_id(vmd_orom, hba->dev_id);
+	vmd_orom->type = SYS_DEV_VMD;
+	return &vmd_orom->orom;
+}
+
 const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
 {
 	const struct imsm_orom *cap = get_orom_by_device_id(hba->dev_id);
@@ -697,9 +797,19 @@ const struct imsm_orom *find_imsm_capability(struct sys_dev *hba)
 
 	if (hba->type == SYS_DEV_NVME)
 		return find_imsm_nvme(hba);
-	if ((cap = find_imsm_efi(hba)) != NULL)
+
+	cap = find_imsm_efi(hba);
+	if (cap)
 		return cap;
-	if ((cap = find_imsm_hba_orom(hba)) != NULL)
+
+	if (hba->type == SYS_DEV_VMD) {
+		cap = find_imsm_vmd(hba);
+		if (cap)
+			return cap;
+	}
+
+	cap = find_imsm_hba_orom(hba);
+	if (cap)
 		return cap;
 
 	return NULL;
diff --git a/platform-intel.h b/platform-intel.h
index 6238d23f..62ad7219 100644
--- a/platform-intel.h
+++ b/platform-intel.h
@@ -24,6 +24,7 @@ struct imsm_orom {
 	__u8 signature[4];
 	#define IMSM_OROM_SIGNATURE "$VER"
 	#define IMSM_NVME_OROM_COMPAT_SIGNATURE "$NVM"
+	#define IMSM_VMD_OROM_COMPAT_SIGNATURE "$VMD"
 	__u8 table_ver_major; /* Currently 2 (can change with future revs) */
 	__u8 table_ver_minor; /* Currently 2 (can change with future revs) */
 	__u16 major_ver; /* Example: 8 as in 8.6.0.1020 */
@@ -65,11 +66,13 @@ struct imsm_orom {
 	__u16 tds; /* Total Disks Supported */
 	#define IMSM_OROM_TOTAL_DISKS 6
 	#define IMSM_OROM_TOTAL_DISKS_NVME 12
+	#define IMSM_OROM_TOTAL_DISKS_VMD 48
 	__u8 vpa; /* # Volumes Per Array supported */
 	#define IMSM_OROM_VOLUMES_PER_ARRAY 2
 	__u8 vphba; /* # Volumes Per Host Bus Adapter supported */
 	#define IMSM_OROM_VOLUMES_PER_HBA 4
 	#define IMSM_OROM_VOLUMES_PER_HBA_NVME 4
+	#define IMSM_OROM_VOLUMES_PER_HBA_VMD 24
 	/* Attributes supported. This should map to the
 	 * attributes in the MPB. Also, lower 16 bits
 	 * should match/duplicate RLC bits above.
@@ -182,7 +185,13 @@ static inline int imsm_orom_is_enterprise(const struct imsm_orom *orom)
 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;
+		      sizeof(orom->signature)) == 0;
+}
+
+static inline int imsm_orom_is_vmd_without_efi(const struct imsm_orom *orom)
+{
+	return memcmp(orom->signature, IMSM_VMD_OROM_COMPAT_SIGNATURE,
+		      sizeof(orom->signature)) == 0;
 }
 
 static inline int imsm_orom_has_tpv_support(const struct imsm_orom *orom)
diff --git a/super-intel.c b/super-intel.c
index a5c86cb2..2a2d006a 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -2646,9 +2646,14 @@ static void print_imsm_capability(const struct imsm_orom *orom)
 	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);
+	if (orom->major_ver || orom->minor_ver || orom->hotfix_ver || orom->build) {
+		if (imsm_orom_is_vmd_without_efi(orom))
+			printf("        Version : %d.%d\n", orom->major_ver,
+			       orom->minor_ver);
+		else
+			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" : "",
-- 
2.26.2




[Index of Archives]     [Linux RAID Wiki]     [ATA RAID]     [Linux SCSI Target Infrastructure]     [Linux Block]     [Linux IDE]     [Linux SCSI]     [Linux Hams]     [Device Mapper]     [Device Mapper Cryptographics]     [Kernel]     [Linux Admin]     [Linux Net]     [GFS]     [RPM]     [git]     [Yosemite Forum]


  Powered by Linux