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