1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (c) Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/thread.h" 7 8 #include "ftl_core.h" 9 #include "ftl_mngt.h" 10 #include "ftl_mngt_steps.h" 11 #include "ftl_band.h" 12 13 struct ftl_io_channel_ctx { 14 struct ftl_io_channel *ioch; 15 }; 16 17 struct ftl_io_channel * 18 ftl_io_channel_get_ctx(struct spdk_io_channel *ioch) 19 { 20 struct ftl_io_channel_ctx *ctx = spdk_io_channel_get_ctx(ioch); 21 return ctx->ioch; 22 } 23 24 static void 25 ftl_dev_register_channel(void *ctx) 26 { 27 struct ftl_io_channel *ioch = ctx; 28 struct spdk_ftl_dev *dev = ioch->dev; 29 30 /* This only runs on the core thread, so it's safe to do this lockless */ 31 TAILQ_INSERT_TAIL(&dev->ioch_queue, ioch, entry); 32 } 33 34 static void 35 io_channel_unregister(void *ctx) 36 { 37 struct ftl_io_channel *ioch = ctx; 38 struct spdk_ftl_dev *dev = ioch->dev; 39 40 TAILQ_REMOVE(&dev->ioch_queue, ioch, entry); 41 42 spdk_ring_free(ioch->cq); 43 spdk_ring_free(ioch->sq); 44 ftl_mempool_destroy(ioch->map_pool); 45 free(ioch); 46 } 47 48 static int 49 io_channel_create_cb(void *io_device, void *ctx) 50 { 51 struct spdk_ftl_dev *dev = io_device; 52 struct ftl_io_channel_ctx *_ioch = ctx; 53 struct ftl_io_channel *ioch; 54 char mempool_name[32]; 55 int rc; 56 57 FTL_NOTICELOG(dev, "FTL IO channel created on %s\n", 58 spdk_thread_get_name(spdk_get_thread())); 59 60 /* This gets unregistered asynchronously with the device - 61 * we can't just use the ctx buffer passed by the thread library 62 */ 63 ioch = calloc(1, sizeof(*ioch)); 64 if (ioch == NULL) { 65 FTL_ERRLOG(dev, "Failed to allocate IO channel\n"); 66 return -1; 67 } 68 69 rc = snprintf(mempool_name, sizeof(mempool_name), "ftl_io_%p", ioch); 70 if (rc < 0 || rc >= (int)sizeof(mempool_name)) { 71 FTL_ERRLOG(dev, "Failed to create IO channel pool name\n"); 72 free(ioch); 73 return -1; 74 } 75 76 ioch->dev = dev; 77 78 ioch->map_pool = ftl_mempool_create( 79 dev->conf.user_io_pool_size, 80 sizeof(ftl_addr) * dev->xfer_size, 81 64, 82 SPDK_ENV_SOCKET_ID_ANY); 83 if (!ioch->map_pool) { 84 FTL_ERRLOG(dev, "Failed to create IO channel's map IO pool\n"); 85 goto fail_io_pool; 86 } 87 88 ioch->cq = spdk_ring_create(SPDK_RING_TYPE_SP_SC, spdk_align64pow2(dev->conf.user_io_pool_size + 1), 89 SPDK_ENV_SOCKET_ID_ANY); 90 if (!ioch->cq) { 91 FTL_ERRLOG(dev, "Failed to create IO channel completion queue\n"); 92 goto fail_io_pool; 93 } 94 95 ioch->sq = spdk_ring_create(SPDK_RING_TYPE_SP_SC, spdk_align64pow2(dev->conf.user_io_pool_size + 1), 96 SPDK_ENV_SOCKET_ID_ANY); 97 if (!ioch->sq) { 98 FTL_ERRLOG(dev, "Failed to create IO channel submission queue\n"); 99 goto fail_cq; 100 } 101 102 ioch->poller = SPDK_POLLER_REGISTER(ftl_io_channel_poll, ioch, 0); 103 if (!ioch->poller) { 104 FTL_ERRLOG(dev, "Failed to register IO channel poller\n"); 105 goto fail_sq; 106 } 107 108 if (spdk_thread_send_msg(dev->core_thread, ftl_dev_register_channel, ioch)) { 109 FTL_ERRLOG(dev, "Failed to register IO channel\n"); 110 goto fail_poller; 111 } 112 113 _ioch->ioch = ioch; 114 return 0; 115 116 fail_poller: 117 spdk_poller_unregister(&ioch->poller); 118 fail_cq: 119 spdk_ring_free(ioch->cq); 120 fail_sq: 121 spdk_ring_free(ioch->sq); 122 fail_io_pool: 123 ftl_mempool_destroy(ioch->map_pool); 124 free(ioch); 125 126 return -1; 127 } 128 129 static void 130 io_channel_destroy_cb(void *io_device, void *ctx) 131 { 132 struct ftl_io_channel_ctx *_ioch = ctx; 133 struct ftl_io_channel *ioch = _ioch->ioch; 134 struct spdk_ftl_dev *dev = ioch->dev; 135 136 FTL_NOTICELOG(dev, "FTL IO channel destroy on %s\n", 137 spdk_thread_get_name(spdk_get_thread())); 138 139 spdk_poller_unregister(&ioch->poller); 140 spdk_thread_send_msg(ftl_get_core_thread(dev), 141 io_channel_unregister, ioch); 142 } 143 144 void 145 ftl_mngt_register_io_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 146 { 147 dev->io_device_registered = true; 148 149 spdk_io_device_register(dev, io_channel_create_cb, 150 io_channel_destroy_cb, 151 sizeof(struct ftl_io_channel_ctx), 152 NULL); 153 154 ftl_mngt_next_step(mngt); 155 } 156 157 static void 158 unregister_cb(void *io_device) 159 { 160 struct spdk_ftl_dev *dev = io_device; 161 struct ftl_mngt_process *mngt = dev->unregister_process; 162 163 dev->io_device_registered = false; 164 dev->unregister_process = NULL; 165 166 ftl_mngt_next_step(mngt); 167 } 168 169 void 170 ftl_mngt_unregister_io_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 171 { 172 if (dev->io_device_registered) { 173 dev->unregister_process = mngt; 174 spdk_io_device_unregister(dev, unregister_cb); 175 } else { 176 ftl_mngt_skip_step(mngt); 177 } 178 } 179 180 void 181 ftl_mngt_init_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 182 { 183 dev->ioch = spdk_get_io_channel(dev); 184 if (!dev->ioch) { 185 FTL_ERRLOG(dev, "Unable to get IO channel for core thread"); 186 ftl_mngt_fail_step(mngt); 187 return; 188 } 189 190 ftl_mngt_next_step(mngt); 191 } 192 193 void 194 ftl_mngt_deinit_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 195 { 196 if (dev->ioch) { 197 spdk_put_io_channel(dev->ioch); 198 dev->ioch = NULL; 199 } 200 201 ftl_mngt_next_step(mngt); 202 } 203