1c6880a39SArtur Paszkiewicz /* SPDX-License-Identifier: BSD-3-Clause
217cf101bSMateusz Kozlowski * Copyright 2023 Solidigm All Rights Reserved
3a6dbe372Spaul luse * Copyright (C) 2022 Intel Corporation.
4c6880a39SArtur Paszkiewicz * All rights reserved.
5c6880a39SArtur Paszkiewicz */
6c6880a39SArtur Paszkiewicz
7c6880a39SArtur Paszkiewicz #include "ftl_sb.h"
8c6880a39SArtur Paszkiewicz #include "ftl_core.h"
9c6880a39SArtur Paszkiewicz #include "ftl_layout.h"
10fa1fc76cSLukasz Lasek #include "upgrade/ftl_sb_upgrade.h"
11fa1fc76cSLukasz Lasek #include "upgrade/ftl_sb_v3.h"
129f42898aSLukasz Lasek #include "upgrade/ftl_sb_v5.h"
13fa1fc76cSLukasz Lasek
14fa1fc76cSLukasz Lasek static bool ftl_superblock_v2_check_magic(union ftl_superblock_ver *sb_ver);
15fa1fc76cSLukasz Lasek
16fa1fc76cSLukasz Lasek struct sb_ops {
17fa1fc76cSLukasz Lasek bool (*check_magic)(union ftl_superblock_ver *sb_ver);
18fa1fc76cSLukasz Lasek
199f42898aSLukasz Lasek bool (*blob_is_empty)(union ftl_superblock_ver *sb_ver);
209f42898aSLukasz Lasek bool (*blob_validate)(struct spdk_ftl_dev *dev);
21fa1fc76cSLukasz Lasek int (*blob_store)(struct spdk_ftl_dev *dev);
22fa1fc76cSLukasz Lasek int (*blob_load)(struct spdk_ftl_dev *dev);
23fa1fc76cSLukasz Lasek
24fa1fc76cSLukasz Lasek int (*upgrade_region)(struct spdk_ftl_dev *dev, struct ftl_layout_region *reg,
25fa1fc76cSLukasz Lasek uint32_t new_version);
269f42898aSLukasz Lasek
279f42898aSLukasz Lasek int (*layout_apply)(struct spdk_ftl_dev *dev);
289f42898aSLukasz Lasek void (*layout_dump)(struct spdk_ftl_dev *dev);
29fa1fc76cSLukasz Lasek };
30fa1fc76cSLukasz Lasek
31fa1fc76cSLukasz Lasek static struct sb_ops *
sb_get_ops(uint64_t version)32fa1fc76cSLukasz Lasek sb_get_ops(uint64_t version)
33fa1fc76cSLukasz Lasek {
34fa1fc76cSLukasz Lasek static struct sb_ops ops[] = {
35fa1fc76cSLukasz Lasek [FTL_SB_VERSION_0] = {
36fa1fc76cSLukasz Lasek .check_magic = ftl_superblock_v2_check_magic,
37fa1fc76cSLukasz Lasek },
38fa1fc76cSLukasz Lasek [FTL_SB_VERSION_1] = {
39fa1fc76cSLukasz Lasek .check_magic = ftl_superblock_v2_check_magic,
40fa1fc76cSLukasz Lasek },
41fa1fc76cSLukasz Lasek [FTL_SB_VERSION_2] = {
42fa1fc76cSLukasz Lasek .check_magic = ftl_superblock_v2_check_magic,
43fa1fc76cSLukasz Lasek },
44fa1fc76cSLukasz Lasek [FTL_SB_VERSION_3] = {
45fa1fc76cSLukasz Lasek .check_magic = ftl_superblock_v3_check_magic,
469f42898aSLukasz Lasek .blob_is_empty = ftl_superblock_v3_md_layout_is_empty,
47fa1fc76cSLukasz Lasek .blob_load = ftl_superblock_v3_md_layout_load_all,
489f42898aSLukasz Lasek .layout_dump = ftl_superblock_v3_md_layout_dump,
49fa1fc76cSLukasz Lasek },
50fa1fc76cSLukasz Lasek [FTL_SB_VERSION_4] = {
51fa1fc76cSLukasz Lasek .check_magic = ftl_superblock_v3_check_magic,
529f42898aSLukasz Lasek .blob_is_empty = ftl_superblock_v3_md_layout_is_empty,
53fa1fc76cSLukasz Lasek .blob_load = ftl_superblock_v3_md_layout_load_all,
549f42898aSLukasz Lasek .layout_dump = ftl_superblock_v3_md_layout_dump,
559f42898aSLukasz Lasek },
569f42898aSLukasz Lasek [FTL_SB_VERSION_5] = {
579f42898aSLukasz Lasek .check_magic = ftl_superblock_v3_check_magic,
589f42898aSLukasz Lasek .blob_is_empty = ftl_superblock_v5_is_blob_area_empty,
599f42898aSLukasz Lasek .blob_validate = ftl_superblock_v5_validate_blob_area,
609f42898aSLukasz Lasek .blob_store = ftl_superblock_v5_store_blob_area,
619f42898aSLukasz Lasek .blob_load = ftl_superblock_v5_load_blob_area,
62*8fc78fd8SMateusz Kozlowski .upgrade_region = ftl_superblock_v5_md_layout_upgrade_region,
639f42898aSLukasz Lasek .layout_apply = ftl_superblock_v5_md_layout_apply,
649f42898aSLukasz Lasek .layout_dump = ftl_superblock_v5_md_layout_dump,
65fa1fc76cSLukasz Lasek },
66fa1fc76cSLukasz Lasek };
67fa1fc76cSLukasz Lasek
68fa1fc76cSLukasz Lasek if (version >= SPDK_COUNTOF(ops)) {
69fa1fc76cSLukasz Lasek return NULL;
70fa1fc76cSLukasz Lasek }
71fa1fc76cSLukasz Lasek
72fa1fc76cSLukasz Lasek return &ops[version];
73fa1fc76cSLukasz Lasek }
74fa1fc76cSLukasz Lasek
75fa1fc76cSLukasz Lasek static bool
ftl_superblock_v2_check_magic(union ftl_superblock_ver * sb_ver)76fa1fc76cSLukasz Lasek ftl_superblock_v2_check_magic(union ftl_superblock_ver *sb_ver)
77fa1fc76cSLukasz Lasek {
78fa1fc76cSLukasz Lasek return sb_ver->header.magic == FTL_SUPERBLOCK_MAGIC_V2;
79fa1fc76cSLukasz Lasek }
80c6880a39SArtur Paszkiewicz
81c6880a39SArtur Paszkiewicz bool
ftl_superblock_check_magic(struct ftl_superblock * sb)82c6880a39SArtur Paszkiewicz ftl_superblock_check_magic(struct ftl_superblock *sb)
83c6880a39SArtur Paszkiewicz {
84fa1fc76cSLukasz Lasek union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb;
85fa1fc76cSLukasz Lasek struct sb_ops *ops = sb_get_ops(sb_ver->header.version);
86fa1fc76cSLukasz Lasek
87fa1fc76cSLukasz Lasek if (!ops || !ops->check_magic) {
88fa1fc76cSLukasz Lasek ftl_abort();
89fa1fc76cSLukasz Lasek return false;
90c8ab874dSKozlowski Mateusz }
91fa1fc76cSLukasz Lasek return ops->check_magic(sb_ver);
92c6880a39SArtur Paszkiewicz }
93fa1fc76cSLukasz Lasek
9444b6d585SArtur Paszkiewicz bool
ftl_superblock_is_blob_area_empty(struct ftl_superblock * sb)959f42898aSLukasz Lasek ftl_superblock_is_blob_area_empty(struct ftl_superblock *sb)
9644b6d585SArtur Paszkiewicz {
97fa1fc76cSLukasz Lasek union ftl_superblock_ver *sb_ver = (union ftl_superblock_ver *)sb;
98fa1fc76cSLukasz Lasek struct sb_ops *ops = sb_get_ops(sb_ver->header.version);
9944b6d585SArtur Paszkiewicz
1009f42898aSLukasz Lasek if (!ops || !ops->blob_is_empty) {
101fa1fc76cSLukasz Lasek ftl_abort();
10244b6d585SArtur Paszkiewicz return false;
10344b6d585SArtur Paszkiewicz }
1049f42898aSLukasz Lasek return ops->blob_is_empty(sb_ver);
1059f42898aSLukasz Lasek }
1069f42898aSLukasz Lasek
1079f42898aSLukasz Lasek bool
ftl_superblock_validate_blob_area(struct spdk_ftl_dev * dev)1089f42898aSLukasz Lasek ftl_superblock_validate_blob_area(struct spdk_ftl_dev *dev)
1099f42898aSLukasz Lasek {
1109f42898aSLukasz Lasek struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
1119f42898aSLukasz Lasek
1129f42898aSLukasz Lasek if (!ops || !ops->blob_validate) {
1139f42898aSLukasz Lasek return true;
1149f42898aSLukasz Lasek }
1159f42898aSLukasz Lasek return ops->blob_validate(dev);
11644b6d585SArtur Paszkiewicz }
11744b6d585SArtur Paszkiewicz
11844b6d585SArtur Paszkiewicz int
ftl_superblock_store_blob_area(struct spdk_ftl_dev * dev)1199f42898aSLukasz Lasek ftl_superblock_store_blob_area(struct spdk_ftl_dev *dev)
12044b6d585SArtur Paszkiewicz {
121fa1fc76cSLukasz Lasek struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
12244b6d585SArtur Paszkiewicz
123fa1fc76cSLukasz Lasek if (!ops || !ops->blob_store) {
124fa1fc76cSLukasz Lasek ftl_abort();
12544b6d585SArtur Paszkiewicz return -1;
12644b6d585SArtur Paszkiewicz }
127fa1fc76cSLukasz Lasek return ops->blob_store(dev);
12844b6d585SArtur Paszkiewicz }
12944b6d585SArtur Paszkiewicz
13044b6d585SArtur Paszkiewicz int
ftl_superblock_load_blob_area(struct spdk_ftl_dev * dev)1319f42898aSLukasz Lasek ftl_superblock_load_blob_area(struct spdk_ftl_dev *dev)
13244b6d585SArtur Paszkiewicz {
133fa1fc76cSLukasz Lasek struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
13444b6d585SArtur Paszkiewicz
135fa1fc76cSLukasz Lasek if (!ops || !ops->blob_load) {
136fa1fc76cSLukasz Lasek ftl_abort();
13744b6d585SArtur Paszkiewicz return -1;
13844b6d585SArtur Paszkiewicz }
139fa1fc76cSLukasz Lasek return ops->blob_load(dev);
1407ff28519SKozlowski Mateusz }
1417ff28519SKozlowski Mateusz
1427ff28519SKozlowski Mateusz int
ftl_superblock_md_layout_upgrade_region(struct spdk_ftl_dev * dev,struct ftl_layout_region * reg,uint32_t new_version)1437ff28519SKozlowski Mateusz ftl_superblock_md_layout_upgrade_region(struct spdk_ftl_dev *dev,
144fa1fc76cSLukasz Lasek struct ftl_layout_region *reg, uint32_t new_version)
1457ff28519SKozlowski Mateusz {
146fa1fc76cSLukasz Lasek struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
1477ff28519SKozlowski Mateusz
148fa1fc76cSLukasz Lasek if (!ops || !ops->upgrade_region) {
149fa1fc76cSLukasz Lasek ftl_abort();
1507ff28519SKozlowski Mateusz return -1;
1517ff28519SKozlowski Mateusz }
152fa1fc76cSLukasz Lasek return ops->upgrade_region(dev, reg, new_version);
1537ff28519SKozlowski Mateusz }
1547ff28519SKozlowski Mateusz
1559f42898aSLukasz Lasek int
ftl_superblock_md_layout_apply(struct spdk_ftl_dev * dev)1569f42898aSLukasz Lasek ftl_superblock_md_layout_apply(struct spdk_ftl_dev *dev)
1579f42898aSLukasz Lasek {
1589f42898aSLukasz Lasek struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
1599f42898aSLukasz Lasek
1609f42898aSLukasz Lasek if (!ops || !ops->layout_apply) {
1619f42898aSLukasz Lasek return 0;
1629f42898aSLukasz Lasek }
1639f42898aSLukasz Lasek return ops->layout_apply(dev);
1649f42898aSLukasz Lasek }
1659f42898aSLukasz Lasek
16644b6d585SArtur Paszkiewicz void
ftl_superblock_md_layout_dump(struct spdk_ftl_dev * dev)16744b6d585SArtur Paszkiewicz ftl_superblock_md_layout_dump(struct spdk_ftl_dev *dev)
16844b6d585SArtur Paszkiewicz {
169fa1fc76cSLukasz Lasek struct sb_ops *ops = sb_get_ops(dev->sb->header.version);
17044b6d585SArtur Paszkiewicz
171fa1fc76cSLukasz Lasek if (!ops || !ops->layout_dump) {
172fa1fc76cSLukasz Lasek ftl_abort();
17344b6d585SArtur Paszkiewicz return;
17444b6d585SArtur Paszkiewicz }
175fa1fc76cSLukasz Lasek return ops->layout_dump(dev);
17644b6d585SArtur Paszkiewicz }
177