]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
imsm: Add reading vmd register for finding imsm capability
authorMateusz Grzonka <mateusz.grzonka@intel.com>
Wed, 5 Jul 2023 14:23:17 +0000 (16:23 +0200)
committerJes Sorensen <jes@trained-monkey.org>
Fri, 1 Sep 2023 16:13:45 +0000 (12:13 -0400)
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@intel.com>
Signed-off-by: Jes Sorensen <jes@trained-monkey.org>
platform-intel.c
platform-intel.h
super-intel.c

index ef90c3fdd1f818c95153892f72f6b608dfc56473..ac282bc5b09b9db50f1fe3c19b5b2badd5a81bea 100644 (file)
@@ -700,6 +700,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);
@@ -709,9 +809,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;
index ba97fb04274a1703264d443dd3b4d5a62bc72b3b..ce29d3da58e48e14a69ae479651db211ba9cc37b 100644 (file)
@@ -27,6 +27,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 */
@@ -68,11 +69,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.
@@ -185,7 +188,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)
index ce813172f1b93b3a8778b9fa4e931ca2af287c1a..77b0066fc47000ee9be341b089372f6f9ebc75c0 100644 (file)
@@ -2672,9 +2672,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" : "",