Line data Source code
1 : /* SPDX-License-Identifier: BSD-3-Clause
2 : * Copyright (C) 2022 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 0 : ftl_io_channel_get_ctx(struct spdk_io_channel *ioch)
19 : {
20 0 : struct ftl_io_channel_ctx *ctx = spdk_io_channel_get_ctx(ioch);
21 0 : return ctx->ioch;
22 : }
23 :
24 : static void
25 0 : ftl_dev_register_channel(void *ctx)
26 : {
27 0 : struct ftl_io_channel *ioch = ctx;
28 0 : 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 0 : TAILQ_INSERT_TAIL(&dev->ioch_queue, ioch, entry);
32 0 : }
33 :
34 : static void
35 0 : io_channel_unregister(void *ctx)
36 : {
37 0 : struct ftl_io_channel *ioch = ctx;
38 0 : struct spdk_ftl_dev *dev = ioch->dev;
39 :
40 0 : TAILQ_REMOVE(&dev->ioch_queue, ioch, entry);
41 :
42 0 : spdk_ring_free(ioch->cq);
43 0 : spdk_ring_free(ioch->sq);
44 0 : ftl_mempool_destroy(ioch->map_pool);
45 0 : free(ioch);
46 0 : }
47 :
48 : static int
49 0 : io_channel_create_cb(void *io_device, void *ctx)
50 : {
51 0 : struct spdk_ftl_dev *dev = io_device;
52 0 : struct ftl_io_channel_ctx *_ioch = ctx;
53 : struct ftl_io_channel *ioch;
54 0 : char mempool_name[32];
55 : int rc;
56 :
57 0 : 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 0 : ioch = calloc(1, sizeof(*ioch));
64 0 : if (ioch == NULL) {
65 0 : FTL_ERRLOG(dev, "Failed to allocate IO channel\n");
66 0 : return -1;
67 : }
68 :
69 0 : rc = snprintf(mempool_name, sizeof(mempool_name), "ftl_io_%p", ioch);
70 0 : if (rc < 0 || rc >= (int)sizeof(mempool_name)) {
71 0 : FTL_ERRLOG(dev, "Failed to create IO channel pool name\n");
72 0 : free(ioch);
73 0 : return -1;
74 : }
75 :
76 0 : ioch->dev = dev;
77 :
78 0 : ioch->map_pool = ftl_mempool_create(
79 : dev->conf.user_io_pool_size,
80 0 : sizeof(ftl_addr) * dev->xfer_size,
81 : 64,
82 : SPDK_ENV_SOCKET_ID_ANY);
83 0 : if (!ioch->map_pool) {
84 0 : FTL_ERRLOG(dev, "Failed to create IO channel's map IO pool\n");
85 0 : goto fail_io_pool;
86 : }
87 :
88 0 : 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 0 : if (!ioch->cq) {
91 0 : FTL_ERRLOG(dev, "Failed to create IO channel completion queue\n");
92 0 : goto fail_io_pool;
93 : }
94 :
95 0 : 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 0 : if (!ioch->sq) {
98 0 : FTL_ERRLOG(dev, "Failed to create IO channel submission queue\n");
99 0 : goto fail_cq;
100 : }
101 :
102 0 : ioch->poller = SPDK_POLLER_REGISTER(ftl_io_channel_poll, ioch, 0);
103 0 : if (!ioch->poller) {
104 0 : FTL_ERRLOG(dev, "Failed to register IO channel poller\n");
105 0 : goto fail_sq;
106 : }
107 :
108 0 : if (spdk_thread_send_msg(dev->core_thread, ftl_dev_register_channel, ioch)) {
109 0 : FTL_ERRLOG(dev, "Failed to register IO channel\n");
110 0 : goto fail_poller;
111 : }
112 :
113 0 : _ioch->ioch = ioch;
114 0 : return 0;
115 :
116 0 : fail_poller:
117 0 : spdk_poller_unregister(&ioch->poller);
118 0 : fail_cq:
119 0 : spdk_ring_free(ioch->cq);
120 0 : fail_sq:
121 0 : spdk_ring_free(ioch->sq);
122 0 : fail_io_pool:
123 0 : ftl_mempool_destroy(ioch->map_pool);
124 0 : free(ioch);
125 :
126 0 : return -1;
127 : }
128 :
129 : static void
130 0 : io_channel_destroy_cb(void *io_device, void *ctx)
131 : {
132 0 : struct ftl_io_channel_ctx *_ioch = ctx;
133 0 : struct ftl_io_channel *ioch = _ioch->ioch;
134 0 : struct spdk_ftl_dev *dev = ioch->dev;
135 :
136 0 : FTL_NOTICELOG(dev, "FTL IO channel destroy on %s\n",
137 : spdk_thread_get_name(spdk_get_thread()));
138 :
139 0 : spdk_poller_unregister(&ioch->poller);
140 0 : spdk_thread_send_msg(ftl_get_core_thread(dev),
141 : io_channel_unregister, ioch);
142 0 : }
143 :
144 : void
145 0 : ftl_mngt_register_io_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
146 : {
147 0 : dev->io_device_registered = true;
148 :
149 0 : 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 0 : ftl_mngt_next_step(mngt);
155 0 : }
156 :
157 : static void
158 0 : unregister_cb(void *io_device)
159 : {
160 0 : struct spdk_ftl_dev *dev = io_device;
161 0 : struct ftl_mngt_process *mngt = dev->unregister_process;
162 :
163 0 : dev->io_device_registered = false;
164 0 : dev->unregister_process = NULL;
165 :
166 0 : ftl_mngt_next_step(mngt);
167 0 : }
168 :
169 : void
170 0 : ftl_mngt_unregister_io_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
171 : {
172 0 : if (dev->io_device_registered) {
173 0 : dev->unregister_process = mngt;
174 0 : spdk_io_device_unregister(dev, unregister_cb);
175 : } else {
176 0 : ftl_mngt_skip_step(mngt);
177 : }
178 0 : }
179 :
180 : void
181 0 : ftl_mngt_init_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
182 : {
183 0 : dev->ioch = spdk_get_io_channel(dev);
184 0 : if (!dev->ioch) {
185 0 : FTL_ERRLOG(dev, "Unable to get IO channel for core thread");
186 0 : ftl_mngt_fail_step(mngt);
187 0 : return;
188 : }
189 :
190 0 : ftl_mngt_next_step(mngt);
191 : }
192 :
193 : void
194 0 : ftl_mngt_deinit_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
195 : {
196 0 : if (dev->ioch) {
197 0 : spdk_put_io_channel(dev->ioch);
198 0 : dev->ioch = NULL;
199 : }
200 :
201 0 : ftl_mngt_next_step(mngt);
202 0 : }
|