1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk/nvme.h" 8 #include "spdk/thread.h" 9 #include "spdk/string.h" 10 #include "spdk/likely.h" 11 #include "spdk/ftl.h" 12 #include "spdk/likely.h" 13 #include "spdk/string.h" 14 #include "spdk/bdev_zone.h" 15 #include "spdk/bdev_module.h" 16 #include "spdk/config.h" 17 18 #include "ftl_core.h" 19 #include "ftl_io.h" 20 #include "ftl_debug.h" 21 #include "ftl_nv_cache.h" 22 #include "ftl_utils.h" 23 #include "mngt/ftl_mngt.h" 24 25 struct ftl_dev_init_ctx { 26 spdk_ftl_init_fn cb_fn; 27 /* Callback's argument */ 28 void *cb_arg; 29 }; 30 31 struct ftl_dev_free_ctx { 32 spdk_ftl_fn cb_fn; 33 /* Callback's argument */ 34 void *cb_arg; 35 }; 36 37 static int 38 init_core_thread(struct spdk_ftl_dev *dev) 39 { 40 struct spdk_cpuset cpumask = {}; 41 42 /* 43 * If core mask is provided create core thread on first cpu that match with the mask, 44 * otherwise use current user thread 45 */ 46 if (dev->conf.core_mask) { 47 if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) { 48 return -EINVAL; 49 } 50 dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask); 51 } else { 52 dev->core_thread = spdk_get_thread(); 53 } 54 55 if (dev->core_thread == NULL) { 56 FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask); 57 return -ENOMEM; 58 } 59 60 return 0; 61 } 62 63 static void 64 exit_thread(void *ctx) 65 { 66 struct spdk_thread *thread = ctx; 67 68 spdk_thread_exit(thread); 69 } 70 71 static void 72 deinit_core_thread(struct spdk_ftl_dev *dev) 73 { 74 if (dev->core_thread && dev->conf.core_mask) { 75 spdk_thread_send_msg(dev->core_thread, exit_thread, 76 dev->core_thread); 77 dev->core_thread = NULL; 78 } 79 } 80 81 static void 82 free_dev(struct spdk_ftl_dev *dev) 83 { 84 if (!dev) { 85 return; 86 } 87 88 deinit_core_thread(dev); 89 spdk_ftl_conf_deinit(&dev->conf); 90 free(dev); 91 } 92 93 static struct spdk_ftl_dev * 94 allocate_dev(const struct spdk_ftl_conf *conf, int *error) 95 { 96 int rc; 97 struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev)); 98 99 if (!dev) { 100 FTL_ERRLOG(dev, "Cannot allocate FTL device\n"); 101 *error = -ENOMEM; 102 return NULL; 103 } 104 105 rc = ftl_conf_init_dev(dev, conf); 106 if (rc) { 107 *error = rc; 108 goto error; 109 } 110 111 rc = init_core_thread(dev); 112 if (rc) { 113 *error = rc; 114 goto error; 115 } 116 117 TAILQ_INIT(&dev->rd_sq); 118 TAILQ_INIT(&dev->wr_sq); 119 TAILQ_INIT(&dev->ioch_queue); 120 121 return dev; 122 error: 123 free_dev(dev); 124 return NULL; 125 } 126 127 static void 128 dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status) 129 { 130 struct ftl_dev_init_ctx *ctx = _ctx; 131 132 if (status) { 133 free_dev(dev); 134 dev = NULL; 135 } 136 ctx->cb_fn(dev, ctx->cb_arg, status); 137 free(ctx); 138 } 139 140 int 141 spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg) 142 { 143 int rc = -1; 144 struct ftl_dev_init_ctx *ctx; 145 struct spdk_ftl_dev *dev = NULL; 146 147 ctx = calloc(1, sizeof(*ctx)); 148 if (!ctx) { 149 rc = -ENOMEM; 150 goto error; 151 } 152 ctx->cb_fn = cb_fn; 153 ctx->cb_arg = cb_arg; 154 155 dev = allocate_dev(conf, &rc); 156 if (!dev) { 157 goto error; 158 } 159 160 rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx); 161 if (rc) { 162 goto error; 163 } 164 165 return 0; 166 167 error: 168 free(ctx); 169 free_dev(dev); 170 return rc; 171 } 172 173 static void 174 dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status) 175 { 176 struct ftl_dev_free_ctx *ctx = _ctx; 177 178 if (!status) { 179 free_dev(dev); 180 } 181 ctx->cb_fn(ctx->cb_arg, status); 182 free(ctx); 183 } 184 185 int 186 spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg) 187 { 188 int rc = -1; 189 struct ftl_dev_free_ctx *ctx; 190 191 ctx = calloc(1, sizeof(*ctx)); 192 if (!ctx) { 193 rc = -ENOMEM; 194 goto error; 195 } 196 ctx->cb_fn = cb_fn; 197 ctx->cb_arg = cb_arg; 198 199 rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx); 200 if (rc) { 201 goto error; 202 } 203 204 return 0; 205 206 error: 207 free(ctx); 208 return rc; 209 } 210 211 SPDK_LOG_REGISTER_COMPONENT(ftl_init) 212