xref: /spdk/lib/ftl/mngt/ftl_mngt_ioch.c (revision 186b109dd3a723612e3df79bb3d97699173d39e3)
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