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