Branch data 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 : 10330590 : ftl_io_channel_get_ctx(struct spdk_io_channel *ioch)
19 : : {
20 : 10330590 : struct ftl_io_channel_ctx *ctx = spdk_io_channel_get_ctx(ioch);
21 : 10330590 : return ctx->ioch;
22 : : }
23 : :
24 : : static void
25 : 42 : ftl_dev_register_channel(void *ctx)
26 : : {
27 : 42 : struct ftl_io_channel *ioch = ctx;
28 : 42 : 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 : 42 : TAILQ_INSERT_TAIL(&dev->ioch_queue, ioch, entry);
32 : 42 : }
33 : :
34 : : static void
35 : 42 : io_channel_unregister(void *ctx)
36 : : {
37 : 42 : struct ftl_io_channel *ioch = ctx;
38 : 42 : struct spdk_ftl_dev *dev = ioch->dev;
39 : :
40 [ + + ]: 42 : TAILQ_REMOVE(&dev->ioch_queue, ioch, entry);
41 : :
42 : 42 : spdk_ring_free(ioch->cq);
43 : 42 : spdk_ring_free(ioch->sq);
44 : 42 : ftl_mempool_destroy(ioch->map_pool);
45 : 42 : free(ioch);
46 : 42 : }
47 : :
48 : : static int
49 : 42 : io_channel_create_cb(void *io_device, void *ctx)
50 : : {
51 : 42 : struct spdk_ftl_dev *dev = io_device;
52 : 42 : struct ftl_io_channel_ctx *_ioch = ctx;
53 : : struct ftl_io_channel *ioch;
54 : 42 : char mempool_name[32];
55 : : int rc;
56 : :
57 [ + - ]: 42 : 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 : 42 : ioch = calloc(1, sizeof(*ioch));
64 [ - + ]: 42 : if (ioch == NULL) {
65 [ # # ]: 0 : FTL_ERRLOG(dev, "Failed to allocate IO channel\n");
66 : 0 : return -1;
67 : : }
68 : :
69 [ - + ]: 42 : rc = snprintf(mempool_name, sizeof(mempool_name), "ftl_io_%p", ioch);
70 [ + - - + ]: 42 : 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 : 42 : ioch->dev = dev;
77 : :
78 : 42 : ioch->map_pool = ftl_mempool_create(
79 : : dev->conf.user_io_pool_size,
80 : 42 : sizeof(ftl_addr) * dev->xfer_size,
81 : : 64,
82 : : SPDK_ENV_SOCKET_ID_ANY);
83 [ - + ]: 42 : 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 : 42 : 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 [ - + ]: 42 : 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 : 42 : 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 [ - + ]: 42 : if (!ioch->sq) {
98 [ # # ]: 0 : FTL_ERRLOG(dev, "Failed to create IO channel submission queue\n");
99 : 0 : goto fail_cq;
100 : : }
101 : :
102 : 42 : ioch->poller = SPDK_POLLER_REGISTER(ftl_io_channel_poll, ioch, 0);
103 [ - + ]: 42 : if (!ioch->poller) {
104 [ # # ]: 0 : FTL_ERRLOG(dev, "Failed to register IO channel poller\n");
105 : 0 : goto fail_sq;
106 : : }
107 : :
108 [ - + ]: 42 : 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 : 42 : _ioch->ioch = ioch;
114 : 42 : 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 : 42 : io_channel_destroy_cb(void *io_device, void *ctx)
131 : : {
132 : 42 : struct ftl_io_channel_ctx *_ioch = ctx;
133 : 42 : struct ftl_io_channel *ioch = _ioch->ioch;
134 : 42 : struct spdk_ftl_dev *dev = ioch->dev;
135 : :
136 [ + - ]: 42 : FTL_NOTICELOG(dev, "FTL IO channel destroy on %s\n",
137 : : spdk_thread_get_name(spdk_get_thread()));
138 : :
139 : 42 : spdk_poller_unregister(&ioch->poller);
140 : 42 : spdk_thread_send_msg(ftl_get_core_thread(dev),
141 : : io_channel_unregister, ioch);
142 : 42 : }
143 : :
144 : : void
145 : 22 : ftl_mngt_register_io_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
146 : : {
147 : 22 : dev->io_device_registered = true;
148 : :
149 : 22 : 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 : 22 : ftl_mngt_next_step(mngt);
155 : 22 : }
156 : :
157 : : static void
158 : 22 : unregister_cb(void *io_device)
159 : : {
160 : 22 : struct spdk_ftl_dev *dev = io_device;
161 : 22 : struct ftl_mngt_process *mngt = dev->unregister_process;
162 : :
163 : 22 : dev->io_device_registered = false;
164 : 22 : dev->unregister_process = NULL;
165 : :
166 : 22 : ftl_mngt_next_step(mngt);
167 : 22 : }
168 : :
169 : : void
170 : 44 : ftl_mngt_unregister_io_device(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
171 : : {
172 [ - + + + ]: 44 : if (dev->io_device_registered) {
173 : 22 : dev->unregister_process = mngt;
174 : 22 : spdk_io_device_unregister(dev, unregister_cb);
175 : : } else {
176 : 22 : ftl_mngt_skip_step(mngt);
177 : : }
178 : 44 : }
179 : :
180 : : void
181 : 22 : ftl_mngt_init_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
182 : : {
183 : 22 : dev->ioch = spdk_get_io_channel(dev);
184 [ - + ]: 22 : 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 : 22 : ftl_mngt_next_step(mngt);
191 : : }
192 : :
193 : : void
194 : 44 : ftl_mngt_deinit_io_channel(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
195 : : {
196 [ + + ]: 44 : if (dev->ioch) {
197 : 22 : spdk_put_io_channel(dev->ioch);
198 : 22 : dev->ioch = NULL;
199 : : }
200 : :
201 : 44 : ftl_mngt_next_step(mngt);
202 : 44 : }
|