1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * Copyright 2023 Solidigm All Rights Reserved 4 * All rights reserved. 5 */ 6 7 #include "ftl_mngt.h" 8 #include "ftl_mngt_steps.h" 9 #include "ftl_internal.h" 10 #include "ftl_core.h" 11 12 struct ftl_mngt_p2l_md_ctx { 13 struct ftl_mngt_process *mngt; 14 int md_region; 15 int md_region_min; 16 int md_region_max; 17 int status; 18 }; 19 20 static void ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx); 21 22 void 23 ftl_mngt_p2l_init_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 24 { 25 if (!ftl_p2l_ckpt_init(dev)) { 26 ftl_mngt_next_step(mngt); 27 } else { 28 ftl_mngt_fail_step(mngt); 29 } 30 } 31 32 void 33 ftl_mngt_p2l_deinit_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 34 { 35 ftl_p2l_ckpt_deinit(dev); 36 ftl_mngt_next_step(mngt); 37 } 38 39 static void 40 ftl_p2l_wipe_md_region_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 41 { 42 struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx; 43 44 if (status) { 45 ftl_mngt_fail_step(ctx->mngt); 46 return; 47 } 48 49 if (ctx->md_region == ctx->md_region_max) { 50 ftl_mngt_next_step(ctx->mngt); 51 return; 52 } 53 54 ctx->md_region++; 55 ftl_p2l_wipe_md_region(dev, ctx); 56 } 57 58 static void 59 ftl_p2l_wipe_md_region(struct spdk_ftl_dev *dev, struct ftl_mngt_p2l_md_ctx *ctx) 60 { 61 struct ftl_layout *layout = &dev->layout; 62 struct ftl_md *md = layout->md[ctx->md_region]; 63 64 assert(ctx->md_region >= ctx->md_region_min); 65 assert(ctx->md_region <= ctx->md_region_max); 66 67 if (!md) { 68 ftl_mngt_fail_step(ctx->mngt); 69 return; 70 } 71 72 md->owner.cb_ctx = ctx; 73 md->cb = ftl_p2l_wipe_md_region_cb; 74 ftl_md_clear(md, 0, NULL); 75 } 76 77 static void 78 ftl_mngt_p2l_wipe_range(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt, int min, int max) 79 { 80 struct ftl_mngt_p2l_md_ctx *ctx; 81 82 if (ftl_mngt_alloc_step_ctx(mngt, sizeof(struct ftl_mngt_p2l_md_ctx))) { 83 ftl_mngt_fail_step(mngt); 84 return; 85 } 86 ctx = ftl_mngt_get_step_ctx(mngt); 87 ctx->mngt = mngt; 88 ctx->md_region_min = min; 89 ctx->md_region_max = max; 90 ctx->md_region = ctx->md_region_min; 91 ftl_p2l_wipe_md_region(dev, ctx); 92 } 93 94 void 95 ftl_mngt_p2l_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 96 { 97 ftl_mngt_p2l_wipe_range(dev, mngt, FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN, 98 FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX); 99 } 100 101 void 102 ftl_mngt_p2l_log_io_wipe(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 103 { 104 struct ftl_layout_region *region; 105 bool wipe = false; 106 107 /* Check if P2L IO logs are enabled and we have to clear this MD and region */ 108 for (int i = FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN; i <= FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX; 109 i++) { 110 region = &dev->layout.region[i]; 111 if (region->current.blocks) { 112 wipe = true; 113 break; 114 } 115 } 116 117 if (!wipe) { 118 ftl_mngt_skip_step(mngt); 119 return; 120 } 121 122 ftl_mngt_p2l_wipe_range(dev, mngt, FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN, 123 FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX); 124 } 125 126 void 127 ftl_mngt_p2l_free_bufs(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 128 { 129 struct ftl_md *md; 130 int region_type; 131 132 for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 133 region_type <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; 134 region_type++) { 135 md = dev->layout.md[region_type]; 136 assert(md); 137 ftl_md_free_buf(md, ftl_md_destroy_region_flags(dev, dev->layout.region[region_type].type)); 138 } 139 ftl_mngt_next_step(mngt); 140 } 141 142 static void 143 ftl_mngt_p2l_restore_ckpt_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status) 144 { 145 struct ftl_mngt_p2l_md_ctx *ctx = md->owner.cb_ctx; 146 assert(ctx); 147 if (status) { 148 ctx->status = status; 149 } 150 151 if (++ctx->md_region == FTL_LAYOUT_REGION_TYPE_P2L_COUNT) { 152 if (!ctx->status) { 153 ftl_mngt_next_step(ctx->mngt); 154 } else { 155 ftl_mngt_fail_step(ctx->mngt); 156 } 157 } 158 } 159 160 void 161 ftl_mngt_p2l_restore_ckpt(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 162 { 163 struct ftl_layout *layout = &dev->layout; 164 struct ftl_md *md; 165 struct ftl_mngt_p2l_md_ctx *ctx; 166 int md_region; 167 168 if (ftl_fast_startup(dev)) { 169 FTL_NOTICELOG(dev, "SHM: skipping p2l ckpt restore\n"); 170 ftl_mngt_next_step(mngt); 171 return; 172 } 173 174 if (ftl_mngt_alloc_step_ctx(mngt, sizeof(struct ftl_mngt_p2l_md_ctx))) { 175 ftl_mngt_fail_step(mngt); 176 return; 177 } 178 ctx = ftl_mngt_get_step_ctx(mngt); 179 ctx->mngt = mngt; 180 ctx->md_region = 0; 181 ctx->status = 0; 182 183 for (md_region = FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MIN; 184 md_region <= FTL_LAYOUT_REGION_TYPE_P2L_CKPT_MAX; md_region++) { 185 md = layout->md[md_region]; 186 assert(md); 187 md->owner.cb_ctx = ctx; 188 md->cb = ftl_mngt_p2l_restore_ckpt_cb; 189 ftl_md_restore(md); 190 } 191 } 192