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