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