1498c39beSLukasz Lasek /* SPDX-License-Identifier: BSD-3-Clause 2498c39beSLukasz Lasek * Copyright 2023 Solidigm All Rights Reserved 3498c39beSLukasz Lasek */ 4498c39beSLukasz Lasek 5498c39beSLukasz Lasek #include "ftl_base_dev.h" 6498c39beSLukasz Lasek #include "ftl_core.h" 7498c39beSLukasz Lasek #include "ftl_layout.h" 89f42898aSLukasz Lasek #include "ftl_band.h" 993036282SLukasz Lasek #include "utils/ftl_layout_tracker_bdev.h" 10498c39beSLukasz Lasek 11498c39beSLukasz Lasek static bool 12498c39beSLukasz Lasek is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev) 13498c39beSLukasz Lasek { 14*e56f1618SMateusz Kozlowski uint64_t write_unit_size = spdk_bdev_get_write_unit_size(bdev); 15*e56f1618SMateusz Kozlowski 16*e56f1618SMateusz Kozlowski if (spdk_bdev_get_block_size(bdev) != FTL_BLOCK_SIZE) { 17*e56f1618SMateusz Kozlowski FTL_ERRLOG(dev, "Unsupported block size, only 4096 is supprted.\nn"); 18*e56f1618SMateusz Kozlowski return false; 19*e56f1618SMateusz Kozlowski } 20*e56f1618SMateusz Kozlowski 21*e56f1618SMateusz Kozlowski if (spdk_bdev_get_md_size(bdev) != 0) { 22*e56f1618SMateusz Kozlowski /* Bdev's metadata is unsupported */ 23*e56f1618SMateusz Kozlowski FTL_ERRLOG(dev, "Unsupported metadata size, sector metadata isn't supported.\n"); 24*e56f1618SMateusz Kozlowski return false; 25*e56f1618SMateusz Kozlowski } 26*e56f1618SMateusz Kozlowski 27*e56f1618SMateusz Kozlowski if (write_unit_size == 1) { 28*e56f1618SMateusz Kozlowski /* No write unit size, all alignments will work out fine */ 29*e56f1618SMateusz Kozlowski return true; 30*e56f1618SMateusz Kozlowski } 31*e56f1618SMateusz Kozlowski 32*e56f1618SMateusz Kozlowski if (!spdk_u32_is_pow2(write_unit_size) || write_unit_size > (MiB / FTL_BLOCK_SIZE)) { 33*e56f1618SMateusz Kozlowski /* Needs to be a power of 2 for current band size (1GiB) restrictions. 34*e56f1618SMateusz Kozlowski * Current buffers are allocated in 1MiB sizes (256 blocks), so it can't be larger than that. 35*e56f1618SMateusz Kozlowski * In the future, if the restriction is relaxed, the ftl_bitmap_buffer_alignment (64 blocks) 36*e56f1618SMateusz Kozlowski * will need to be taken into consideration as well. 37*e56f1618SMateusz Kozlowski */ 38*e56f1618SMateusz Kozlowski FTL_ERRLOG(dev, 39*e56f1618SMateusz Kozlowski "Unsupported write unit size (%lu), must be a power of 2 (in blocks). Can't be larger than 256 (1MiB)\n", 40*e56f1618SMateusz Kozlowski write_unit_size); 41*e56f1618SMateusz Kozlowski return false; 42*e56f1618SMateusz Kozlowski } 43*e56f1618SMateusz Kozlowski 44*e56f1618SMateusz Kozlowski return true; 45498c39beSLukasz Lasek } 46498c39beSLukasz Lasek 47424a88a4SMateusz Kozlowski static void 48424a88a4SMateusz Kozlowski md_region_setup(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 49424a88a4SMateusz Kozlowski struct ftl_layout_region *region) 50424a88a4SMateusz Kozlowski { 51424a88a4SMateusz Kozlowski assert(region); 52424a88a4SMateusz Kozlowski region->type = reg_type; 53424a88a4SMateusz Kozlowski region->mirror_type = FTL_LAYOUT_REGION_TYPE_INVALID; 54424a88a4SMateusz Kozlowski region->name = ftl_md_region_name(reg_type); 55424a88a4SMateusz Kozlowski 56424a88a4SMateusz Kozlowski region->bdev_desc = dev->base_bdev_desc; 57424a88a4SMateusz Kozlowski region->ioch = dev->base_ioch; 58424a88a4SMateusz Kozlowski region->vss_blksz = 0; 59424a88a4SMateusz Kozlowski } 60424a88a4SMateusz Kozlowski 619f42898aSLukasz Lasek static int 62498c39beSLukasz Lasek md_region_create(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, 639f42898aSLukasz Lasek uint32_t reg_version, size_t reg_blks) 64498c39beSLukasz Lasek { 6593036282SLukasz Lasek const struct ftl_layout_tracker_bdev_region_props *reg_props; 669f42898aSLukasz Lasek uint64_t data_base_alignment; 67498c39beSLukasz Lasek 68498c39beSLukasz Lasek assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 699f42898aSLukasz Lasek reg_blks = ftl_md_region_align_blocks(dev, reg_blks); 70498c39beSLukasz Lasek 71498c39beSLukasz Lasek /* Allocating a ftl_bitmap requires a 8B input buffer alignment, since we're reusing the global valid map md buffer 72498c39beSLukasz Lasek * this means that each band starting address needs to be aligned too - each device sector takes 1b in the valid map, 73498c39beSLukasz Lasek * so 64 sectors (8*8) is the needed alignment 74498c39beSLukasz Lasek */ 7593036282SLukasz Lasek data_base_alignment = 8 * ftl_bitmap_buffer_alignment; 7693036282SLukasz Lasek reg_props = ftl_layout_tracker_bdev_add_region(dev->base_layout_tracker, reg_type, reg_version, 7793036282SLukasz Lasek reg_blks, data_base_alignment); 7893036282SLukasz Lasek if (!reg_props) { 799f42898aSLukasz Lasek return -1; 8093036282SLukasz Lasek } 8193036282SLukasz Lasek assert(reg_props->type == reg_type); 8293036282SLukasz Lasek assert(reg_props->ver == reg_version); 8393036282SLukasz Lasek assert(reg_props->blk_sz == reg_blks); 8493036282SLukasz Lasek assert(reg_props->blk_offs + reg_blks <= dev->layout.base.total_blocks); 859f42898aSLukasz Lasek return 0; 869f42898aSLukasz Lasek } 87498c39beSLukasz Lasek 889f42898aSLukasz Lasek static int 899f42898aSLukasz Lasek md_region_open(struct spdk_ftl_dev *dev, enum ftl_layout_region_type reg_type, uint32_t reg_version, 909f42898aSLukasz Lasek size_t entry_size, size_t entry_count, struct ftl_layout_region *region) 919f42898aSLukasz Lasek { 929f42898aSLukasz Lasek const struct ftl_layout_tracker_bdev_region_props *reg_search_ctx = NULL; 939f42898aSLukasz Lasek uint64_t reg_blks = ftl_md_region_blocks(dev, entry_size * entry_count); 949f42898aSLukasz Lasek 959f42898aSLukasz Lasek assert(reg_type < FTL_LAYOUT_REGION_TYPE_MAX); 969f42898aSLukasz Lasek 979f42898aSLukasz Lasek while (true) { 989f42898aSLukasz Lasek ftl_layout_tracker_bdev_find_next_region(dev->base_layout_tracker, reg_type, ®_search_ctx); 999f42898aSLukasz Lasek if (!reg_search_ctx || reg_search_ctx->ver == reg_version) { 1009f42898aSLukasz Lasek break; 1019f42898aSLukasz Lasek } 1029f42898aSLukasz Lasek } 1039f42898aSLukasz Lasek 1049f42898aSLukasz Lasek if (!reg_search_ctx || reg_search_ctx->blk_sz < reg_blks) { 1059f42898aSLukasz Lasek /* Region not found or insufficient space */ 1069f42898aSLukasz Lasek return -1; 1079f42898aSLukasz Lasek } 1089f42898aSLukasz Lasek 1099f42898aSLukasz Lasek if (!region) { 1109f42898aSLukasz Lasek return 0; 1119f42898aSLukasz Lasek } 1129f42898aSLukasz Lasek 113424a88a4SMateusz Kozlowski md_region_setup(dev, reg_type, region); 114424a88a4SMateusz Kozlowski 115498c39beSLukasz Lasek region->entry_size = entry_size / FTL_BLOCK_SIZE; 116498c39beSLukasz Lasek region->num_entries = entry_count; 117498c39beSLukasz Lasek 1188fc78fd8SMateusz Kozlowski region->current.version = reg_version; 1199f42898aSLukasz Lasek region->current.offset = reg_search_ctx->blk_offs; 1209f42898aSLukasz Lasek region->current.blocks = reg_search_ctx->blk_sz; 1219f42898aSLukasz Lasek 1229f42898aSLukasz Lasek return 0; 123498c39beSLukasz Lasek } 124498c39beSLukasz Lasek 125498c39beSLukasz Lasek struct ftl_base_device_type base_bdev = { 126498c39beSLukasz Lasek .name = "base_bdev", 127498c39beSLukasz Lasek .ops = { 128498c39beSLukasz Lasek .is_bdev_compatible = is_bdev_compatible, 1299f42898aSLukasz Lasek 130498c39beSLukasz Lasek .md_layout_ops = { 131498c39beSLukasz Lasek .region_create = md_region_create, 1329f42898aSLukasz Lasek .region_open = md_region_open, 133498c39beSLukasz Lasek }, 134498c39beSLukasz Lasek } 135498c39beSLukasz Lasek }; 136498c39beSLukasz Lasek FTL_BASE_DEVICE_TYPE_REGISTER(base_bdev) 137