1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2022 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "ftl_l2p.h"
7 #include "ftl_core.h"
8 #include "ftl_band.h"
9 #include "ftl_utils.h"
10 #include "ftl_l2p_flat.h"
11 #include "utils/ftl_addr_utils.h"
12
13 static struct ftl_md *
get_l2p_md(struct spdk_ftl_dev * dev)14 get_l2p_md(struct spdk_ftl_dev *dev)
15 {
16 return dev->layout.md[FTL_LAYOUT_REGION_TYPE_L2P];
17 }
18
19 struct ftl_l2p_flat {
20 void *l2p;
21 bool is_halted;
22 };
23
24 void
ftl_l2p_flat_pin(struct spdk_ftl_dev * dev,struct ftl_l2p_pin_ctx * pin_ctx)25 ftl_l2p_flat_pin(struct spdk_ftl_dev *dev, struct ftl_l2p_pin_ctx *pin_ctx)
26 {
27 assert(dev->num_lbas >= pin_ctx->lba + pin_ctx->count);
28
29 ftl_l2p_pin_complete(dev, 0, pin_ctx);
30 }
31
32 void
ftl_l2p_flat_unpin(struct spdk_ftl_dev * dev,uint64_t lba,uint64_t count)33 ftl_l2p_flat_unpin(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t count)
34 {
35 assert(dev->num_lbas >= lba + count);
36 }
37
38 void
ftl_l2p_flat_set(struct spdk_ftl_dev * dev,uint64_t lba,ftl_addr addr)39 ftl_l2p_flat_set(struct spdk_ftl_dev *dev, uint64_t lba, ftl_addr addr)
40 {
41 struct ftl_l2p_flat *l2p_flat = dev->l2p;
42
43 assert(dev->num_lbas > lba);
44
45 ftl_addr_store(dev, l2p_flat->l2p, lba, addr);
46 }
47
48 ftl_addr
ftl_l2p_flat_get(struct spdk_ftl_dev * dev,uint64_t lba)49 ftl_l2p_flat_get(struct spdk_ftl_dev *dev, uint64_t lba)
50 {
51 struct ftl_l2p_flat *l2p_flat = dev->l2p;
52
53 assert(dev->num_lbas > lba);
54
55 return ftl_addr_load(dev, l2p_flat->l2p, lba);
56 }
57
58 static void
md_cb(struct spdk_ftl_dev * dev,struct ftl_md * md,int status)59 md_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
60 {
61 ftl_l2p_cb cb = md->owner.private;
62 void *cb_ctx = md->owner.cb_ctx;
63
64 cb(dev, status, cb_ctx);
65 }
66
67 void
ftl_l2p_flat_clear(struct spdk_ftl_dev * dev,ftl_l2p_cb cb,void * cb_ctx)68 ftl_l2p_flat_clear(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
69 {
70 struct ftl_l2p_flat *l2p_flat = dev->l2p;
71 struct ftl_md *md;
72
73 memset(l2p_flat->l2p, (int)FTL_ADDR_INVALID,
74 ftl_md_get_buffer_size(get_l2p_md(dev)));
75
76 md = get_l2p_md(dev);
77 md->cb = md_cb;
78 md->owner.cb_ctx = cb_ctx;
79 md->owner.private = cb;
80 ftl_md_persist(md);
81 }
82
83 void
ftl_l2p_flat_restore(struct spdk_ftl_dev * dev,ftl_l2p_cb cb,void * cb_ctx)84 ftl_l2p_flat_restore(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
85 {
86 struct ftl_md *md;
87
88 md = get_l2p_md(dev);
89 md->cb = md_cb;
90 md->owner.cb_ctx = cb_ctx;
91 md->owner.private = cb;
92 ftl_md_restore(md);
93 }
94
95 void
ftl_l2p_flat_persist(struct spdk_ftl_dev * dev,ftl_l2p_cb cb,void * cb_ctx)96 ftl_l2p_flat_persist(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
97 {
98 struct ftl_md *md;
99
100 md = get_l2p_md(dev);
101 md->cb = md_cb;
102 md->owner.cb_ctx = cb_ctx;
103 md->owner.private = cb;
104 ftl_md_persist(md);
105 }
106
107 static int
ftl_l2p_flat_init_dram(struct spdk_ftl_dev * dev,struct ftl_l2p_flat * l2p_flat,size_t l2p_size)108 ftl_l2p_flat_init_dram(struct spdk_ftl_dev *dev, struct ftl_l2p_flat *l2p_flat,
109 size_t l2p_size)
110 {
111 struct ftl_md *md = get_l2p_md(dev);
112
113 assert(ftl_md_get_buffer_size(md) >= l2p_size);
114
115 l2p_flat->l2p = ftl_md_get_buffer(md);
116 if (!l2p_flat->l2p) {
117 FTL_ERRLOG(dev, "Failed to allocate l2p table\n");
118 return -1;
119 }
120
121 return 0;
122 }
123
124 int
ftl_l2p_flat_init(struct spdk_ftl_dev * dev)125 ftl_l2p_flat_init(struct spdk_ftl_dev *dev)
126 {
127 size_t l2p_size = dev->num_lbas * dev->layout.l2p.addr_size;
128 struct ftl_l2p_flat *l2p_flat;
129 int ret;
130
131 if (dev->num_lbas == 0) {
132 FTL_ERRLOG(dev, "Invalid l2p table size\n");
133 return -1;
134 }
135
136 if (dev->l2p) {
137 FTL_ERRLOG(dev, "L2p table already allocated\n");
138 return -1;
139 }
140
141 l2p_flat = calloc(1, sizeof(*l2p_flat));
142 if (!l2p_flat) {
143 FTL_ERRLOG(dev, "Failed to allocate l2p_flat\n");
144 return -1;
145 }
146
147 ret = ftl_l2p_flat_init_dram(dev, l2p_flat, l2p_size);
148
149 if (ret) {
150 free(l2p_flat);
151 return ret;
152 }
153
154 dev->l2p = l2p_flat;
155 return 0;
156 }
157
158 void
ftl_l2p_flat_deinit(struct spdk_ftl_dev * dev)159 ftl_l2p_flat_deinit(struct spdk_ftl_dev *dev)
160 {
161 struct ftl_l2p_flat *l2p_flat = dev->l2p;
162
163 if (!l2p_flat) {
164 return;
165 }
166
167 free(l2p_flat);
168
169 dev->l2p = NULL;
170 }
171
172 void
ftl_l2p_flat_trim(struct spdk_ftl_dev * dev,ftl_l2p_cb cb,void * cb_ctx)173 ftl_l2p_flat_trim(struct spdk_ftl_dev *dev, ftl_l2p_cb cb, void *cb_ctx)
174 {
175 cb(dev, 0, cb_ctx);
176 }
177
178 void
ftl_l2p_flat_process(struct spdk_ftl_dev * dev)179 ftl_l2p_flat_process(struct spdk_ftl_dev *dev)
180 {
181 }
182
183 bool
ftl_l2p_flat_is_halted(struct spdk_ftl_dev * dev)184 ftl_l2p_flat_is_halted(struct spdk_ftl_dev *dev)
185 {
186 return true;
187 }
188
189 void
ftl_l2p_flat_halt(struct spdk_ftl_dev * dev)190 ftl_l2p_flat_halt(struct spdk_ftl_dev *dev)
191 {
192 }
193
194 void
ftl_l2p_flat_resume(struct spdk_ftl_dev * dev)195 ftl_l2p_flat_resume(struct spdk_ftl_dev *dev)
196 {
197 }
198